Sound clip NLA Strips for Nexyon

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.
This commit is contained in:
Joshua Leung 2011-08-07 12:27:20 +00:00
parent 2d884fc035
commit 022e815fbd
12 changed files with 223 additions and 31 deletions

@ -173,6 +173,7 @@ class NLA_MT_add(bpy.types.Menu):
layout.column() layout.column()
layout.operator("nla.actionclip_add") layout.operator("nla.actionclip_add")
layout.operator("nla.transition_add") layout.operator("nla.transition_add")
layout.operator("nla.soundclip_add")
layout.separator() layout.separator()
layout.operator("nla.meta_add") layout.operator("nla.meta_add")

@ -39,6 +39,8 @@ struct AnimData;
struct NlaStrip; struct NlaStrip;
struct NlaTrack; struct NlaTrack;
struct bAction; struct bAction;
struct Scene;
struct Speaker;
/* ----------------------------- */ /* ----------------------------- */
/* Data Management */ /* Data Management */
@ -54,6 +56,7 @@ void copy_nladata(ListBase *dst, ListBase *src);
struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev); struct NlaTrack *add_nlatrack(struct AnimData *adt, struct NlaTrack *prev);
struct NlaStrip *add_nlastrip(struct bAction *act); struct NlaStrip *add_nlastrip(struct bAction *act);
struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, 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 */ /* API */

@ -1921,6 +1921,9 @@ void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, ListBase *modifiers
case NLASTRIP_TYPE_META: /* meta */ case NLASTRIP_TYPE_META: /* meta */
nlastrip_evaluate_meta(ptr, channels, modifiers, nes); nlastrip_evaluate_meta(ptr, channels, modifiers, nes);
break; break;
default: /* do nothing */
break;
} }
/* clear temp recursion safe-check */ /* clear temp recursion safe-check */

@ -46,6 +46,8 @@
#include "DNA_anim_types.h" #include "DNA_anim_types.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "DNA_sound_types.h"
#include "DNA_speaker_types.h"
#include "BKE_action.h" #include "BKE_action.h"
#include "BKE_fcurve.h" #include "BKE_fcurve.h"
@ -53,6 +55,9 @@
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_library.h" #include "BKE_library.h"
#ifdef WITH_AUDASPACE
# include "AUD_C-API.h"
#endif
#include "RNA_access.h" #include "RNA_access.h"
#include "nla_private.h" #include "nla_private.h"
@ -337,6 +342,41 @@ NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
return strip; 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 */ /* NLA Evaluation <-> Editing Stuff */

@ -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 * 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 * 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 * 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) * 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
* 4) normal keyframes: only when there is an active action * 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 ----------- */ case OB_SPEAKER: /* ---------- Speaker ----------- */
{ {
Speaker *spk= (Speaker *)ob->data; Speaker *spk= (Speaker *)ob->data;
type= ANIMTYPE_DSSPK; type= ANIMTYPE_DSSPK;
expanded= FILTER_SPK_OBJD(spk); expanded= FILTER_SPK_OBJD(spk);
} }

@ -213,6 +213,24 @@ static int nla_strip_actclip_panel_poll(const bContext *C, PanelType *UNUSED(pt)
return (strip->type == NLASTRIP_TYPE_CLIP); 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 */ /* active AnimData */
@ -278,6 +296,7 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
uiLayout *layout= pa->layout; uiLayout *layout= pa->layout;
uiLayout *column, *row, *subcol; uiLayout *column, *row, *subcol;
uiBlock *block; uiBlock *block;
short showEvalProps = 1;
if (!nla_panel_context(C, NULL, NULL, &strip_ptr)) if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
return; 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_start", 0, NULL, ICON_NONE);
uiItemR(column, &strip_ptr, "frame_end", 0, NULL, ICON_NONE); uiItemR(column, &strip_ptr, "frame_end", 0, NULL, ICON_NONE);
/* extrapolation */ /* Evaluation-Related Strip Properties ------------------ */
row= uiLayoutRow(layout, 1);
uiItemR(row, &strip_ptr, "extrapolation", 0, NULL, ICON_NONE);
/* blending */ /* sound properties strips don't have these settings */
row= uiLayoutRow(layout, 1); if (RNA_enum_get(&strip_ptr, "type") == NLASTRIP_TYPE_SOUND)
uiItemR(row, &strip_ptr, "blend_type", 0, NULL, ICON_NONE); showEvalProps = 0;
/* only show if allowed to... */
if (showEvalProps) {
/* extrapolation */
row= uiLayoutRow(layout, 1);
uiItemR(row, &strip_ptr, "extrapolation", 0, NULL, ICON_NONE);
/* blend in/out + autoblending /* blending */
* - blend in/out can only be set when autoblending is off row= uiLayoutRow(layout, 1);
*/ uiItemR(row, &strip_ptr, "blend_type", 0, NULL, ICON_NONE);
column= uiLayoutColumn(layout, 1);
uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence")==0); /* blend in/out + autoblending
uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle? * - blend in/out can only be set when autoblending is off
*/
subcol= uiLayoutColumn(column, 1); column= uiLayoutColumn(layout, 1);
uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "use_auto_blend")==0); uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence")==0);
uiItemR(subcol, &strip_ptr, "blend_in", 0, NULL, ICON_NONE); uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle?
uiItemR(subcol, &strip_ptr, "blend_out", 0, NULL, ICON_NONE);
subcol= uiLayoutColumn(column, 1);
/* settings */ uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "use_auto_blend")==0);
column= uiLayoutColumn(layout, 1); uiItemR(subcol, &strip_ptr, "blend_in", 0, NULL, ICON_NONE);
uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || RNA_boolean_get(&strip_ptr, "use_animated_time"))); uiItemR(subcol, &strip_ptr, "blend_out", 0, NULL, ICON_NONE);
uiItemL(column, "Playback Settings:", ICON_NONE);
uiItemR(column, &strip_ptr, "mute", 0, NULL, ICON_NONE); /* settings */
uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE); 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->idname, "NLA_PT_evaluation");
strcpy(pt->label, "Evaluation"); strcpy(pt->label, "Evaluation");
pt->draw= nla_panel_evaluation; pt->draw= nla_panel_evaluation;
pt->poll= nla_strip_panel_poll; pt->poll= nla_strip_eval_panel_poll;
BLI_addtail(&art->paneltypes, pt); BLI_addtail(&art->paneltypes, pt);
pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers"); pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
strcpy(pt->idname, "NLA_PT_modifiers"); strcpy(pt->idname, "NLA_PT_modifiers");
strcpy(pt->label, "Modifiers"); strcpy(pt->label, "Modifiers");
pt->draw= nla_panel_modifiers; pt->draw= nla_panel_modifiers;
pt->poll= nla_strip_panel_poll; pt->poll= nla_strip_eval_panel_poll;
BLI_addtail(&art->paneltypes, pt); BLI_addtail(&art->paneltypes, pt);
} }

@ -198,7 +198,24 @@ static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float co
color[1]= 0.15f; color[1]= 0.15f;
color[2]= 0.26f; 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 { else {
/* Action Clip (default/normal type of strip) */ /* Action Clip (default/normal type of strip) */
if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) { if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) {

@ -36,6 +36,7 @@
#include <math.h> #include <math.h>
#include "DNA_anim_types.h" #include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "MEM_guardedalloc.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 */ /* check if there's space between the two */
if (IS_EQ(s1->end, s2->start)) if (IS_EQ(s1->end, s2->start))
continue; continue;
/* make neither one is a transition /* make sure neither one is a transition
* - although this is impossible to create with the standard tools, * - although this is impossible to create with the standard tools,
* the user may have altered the settings * the user may have altered the settings
*/ */
if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type)) if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type))
continue; continue;
/* also make sure neither one is a soundclip */
if (ELEM(NLASTRIP_TYPE_SOUND, s1->type, s2->type))
continue;
/* allocate new strip */ /* allocate new strip */
strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip"); strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
@ -608,6 +612,91 @@ void NLA_OT_transition_add (wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 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 Meta-Strip Operator ***************************** */
/* Add new meta-strips incorporating the selected strips */ /* Add new meta-strips incorporating the selected strips */
@ -1923,6 +2012,10 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
continue; 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 */ /* add F-Modifier of specified type to selected, and make it the active one */
fcm= add_fmodifier(&strip->modifiers, type); fcm= add_fmodifier(&strip->modifiers, type);

@ -99,6 +99,7 @@ void NLA_OT_view_selected(wmOperatorType *ot);
void NLA_OT_actionclip_add(wmOperatorType *ot); void NLA_OT_actionclip_add(wmOperatorType *ot);
void NLA_OT_transition_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_add(wmOperatorType *ot);
void NLA_OT_meta_remove(wmOperatorType *ot); void NLA_OT_meta_remove(wmOperatorType *ot);

@ -140,6 +140,7 @@ void nla_operatortypes(void)
WM_operatortype_append(NLA_OT_actionclip_add); WM_operatortype_append(NLA_OT_actionclip_add);
WM_operatortype_append(NLA_OT_transition_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_add);
WM_operatortype_append(NLA_OT_meta_remove); WM_operatortype_append(NLA_OT_meta_remove);
@ -233,6 +234,7 @@ static void nla_keymap_main (wmKeyConfig *keyconf, wmKeyMap *keymap)
/* add strips */ /* add strips */
WM_keymap_add_item(keymap, "NLA_OT_actionclip_add", AKEY, KM_PRESS, KM_SHIFT, 0); 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_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 */ /* meta-strips */
WM_keymap_add_item(keymap, "NLA_OT_meta_add", GKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "NLA_OT_meta_add", GKEY, KM_PRESS, KM_SHIFT, 0);

@ -651,7 +651,10 @@ typedef enum eNlaStrip_Type {
/* 'transition' - blends between the adjacent strips */ /* 'transition' - blends between the adjacent strips */
NLASTRIP_TYPE_TRANSITION, NLASTRIP_TYPE_TRANSITION,
/* 'meta' - a strip which acts as a container for a few others */ /* '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; } eNlaStrip_Type;
/* NLA Tracks ------------------------------------- */ /* NLA Tracks ------------------------------------- */

@ -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_CLIP, "CLIP", 0, "Action Clip", "NLA Strip references some Action"},
{NLASTRIP_TYPE_TRANSITION, "TRANSITION", 0, "Transition", "NLA Strip 'transitions' between adjacent strips"}, {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_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}}; {0, NULL, 0, NULL, NULL}};
/* struct definition */ /* 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? */ RNA_def_property_update(prop, NC_ANIMATION|ND_NLA, NULL); /* this will do? */
/* Action */ /* Action */
// TODO: this should only be editable if it is not being edited atm...
prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE); prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "act"); RNA_def_property_pointer_sdna(prop, NULL, "act");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Action_id_poll"); RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Action_id_poll");