diff options
-rw-r--r-- | source/blender/blenkernel/BKE_key.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/key.c | 25 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_channels_defines.c | 198 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_channels_edit.c | 32 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_filter.c | 82 | ||||
-rw-r--r-- | source/blender/editors/include/ED_anim_api.h | 10 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_key_types.h | 6 |
7 files changed, 314 insertions, 40 deletions
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 4bfa6a41099..1b4cbc1cf2a 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -65,6 +65,7 @@ struct Key *ob_get_key(struct Object *ob); struct KeyBlock *ob_get_keyblock(struct Object *ob); struct KeyBlock *key_get_keyblock(struct Key *key, int index); struct KeyBlock *key_get_named_keyblock(struct Key *key, const char name[]); +char *key_get_curValue_rnaPath(struct Key *key, struct KeyBlock *kb); // needed for the GE void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, int mode); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index b6e4ffd6cc3..3fffdef478b 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -35,6 +35,8 @@ #include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" + #include "DNA_anim_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" @@ -57,7 +59,7 @@ #include "BKE_object.h" #include "BKE_utildefines.h" -#include "BLI_blenlib.h" +#include "RNA_access.h" #ifdef HAVE_CONFIG_H @@ -1489,3 +1491,24 @@ KeyBlock *key_get_named_keyblock(Key *key, const char name[]) return NULL; } + +/* Get RNA-Path for 'value' setting of the given ShapeKey + * NOTE: the user needs to free the returned string once they're finishe with it + */ +char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb) +{ + PointerRNA ptr; + PropertyRNA *prop; + + /* sanity checks */ + if ELEM(NULL, key, kb) + return NULL; + + /* create the RNA pointer */ + RNA_pointer_create(key, &RNA_ShapeKey, kb, &ptr); + /* get pointer to the property too */ + prop= RNA_struct_find_property(&ptr, "value"); + + /* return the path */ + return RNA_path_from_ID_to_property(&ptr, prop); +} diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 7c9814eda7b..2cd41b0ffb7 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -1386,7 +1386,7 @@ static int acf_dsskey_setting_flag(int setting, short *neg) switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ - return KEYBLOCK_DS_EXPAND; + return KEY_DS_EXPAND; case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ return ADT_NLA_EVAL_OFF; @@ -1737,28 +1737,91 @@ static bAnimChannelType ACF_DSARM= /* ShapeKey Entry ------------------------------------------- */ -// XXX ... this is currently obsolete... -#if 0 -static void dummy_olddraw_shapekeys () +/* name for ShapeKey */ +static void acf_shapekey_name(bAnimListElem *ale, char *name) { - case ANIMTYPE_SHAPEKEY: /* shapekey channel */ - { - KeyBlock *kb = (KeyBlock *)ale->data; + KeyBlock *kb= (KeyBlock *)ale->data; + + /* just copy the name... */ + if (kb && name) { + /* if the KeyBlock had a name, use it, otherwise use the index */ + if (kb->name[0]) + strcpy(name, kb->name); + else + sprintf(name, "Key %d", ale->index); + } +} + +/* check if some setting exists for this channel */ +static short acf_shapekey_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) +{ + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + case ACHANNEL_SETTING_MUTE: /* muted */ + case ACHANNEL_SETTING_PROTECT: /* protected */ + return 1; + + /* nothing else is supported */ + default: + return 0; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_shapekey_setting_flag(int setting, short *neg) +{ + /* clear extra return data first */ + *neg= 0; + + switch (setting) { + case ACHANNEL_SETTING_MUTE: /* mute */ + return KEYBLOCK_MUTE; - indent = 0; - special = -1; + case ACHANNEL_SETTING_SELECT: /* selected */ + return KEYBLOCK_SEL; - offset= (ale->id) ? 21 : 0; + case ACHANNEL_SETTING_PROTECT: /* locked */ + return KEYBLOCK_LOCKED; - if (kb->name[0] == '\0') - sprintf(name, "Key %d", ale->index); - else - strcpy(name, kb->name); + default: /* unsupported */ + return 0; } - break; } -#endif + +/* get pointer to the setting */ +static void *acf_shapekey_setting_ptr(bAnimListElem *ale, int setting, short *type) +{ + KeyBlock *kb= (KeyBlock *)ale->data; + + /* clear extra return data first */ + *type= 0; + + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + case ACHANNEL_SETTING_MUTE: /* muted */ + case ACHANNEL_SETTING_PROTECT: /* protected */ + GET_ACF_FLAG_PTR(kb->flag) + + default: /* unsupported */ + return NULL; + } +} + +/* shapekey expander type define */ +static bAnimChannelType ACF_SHAPEKEY= +{ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indention_0, /* indent level */ + acf_generic_basic_offset, /* offset */ + + acf_shapekey_name, /* name */ + NULL, /* icon */ + + acf_shapekey_setting_valid, /* has setting */ + acf_shapekey_setting_flag, /* flag for setting */ + acf_shapekey_setting_ptr /* pointer for setting */ +}; /* Grease Pencil entries ------------------------------------------- */ // XXX ... this is currently not restored yet @@ -1923,7 +1986,7 @@ void ANIM_init_channel_typeinfo_data (void) animchannelTypeInfo[type++]= &ACF_DSMBALL; /* MetaBall Channel */ animchannelTypeInfo[type++]= &ACF_DSARM; /* Armature Channel */ - animchannelTypeInfo[type++]= NULL; /* ShapeKey */ // XXX this is no longer used for now... + animchannelTypeInfo[type++]= &ACF_SHAPEKEY; /* ShapeKey */ // XXX not restored yet animchannelTypeInfo[type++]= NULL; /* Grease Pencil Datablock */ @@ -2237,7 +2300,57 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi } } - +/* callback for shapekey widget sliders - insert keyframes */ +static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, void *kb_poin) +{ + Key *key= (Key *)key_poin; + KeyBlock *kb= (KeyBlock *)kb_poin; + char *rna_path= key_get_curValue_rnaPath(key, kb); + + Scene *scene= CTX_data_scene(C); + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + short flag=0, done=0; + float cfra; + + /* get current frame */ + // NOTE: this will do for now... + cfra= (float)CFRA; + + /* get flags for keyframing */ + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + flag |= INSERTKEY_NEEDED; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) + flag |= INSERTKEY_MATRIX; + if (IS_AUTOKEY_MODE(scene, EDITKEYS)) + flag |= INSERTKEY_REPLACE; + + + /* get RNA pointer, and resolve the path */ + RNA_id_pointer_create((ID *)key, &id_ptr); + + /* try to resolve the path stored in the F-Curve */ + if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) { + /* find or create new F-Curve */ + // XXX is the group name for this ok? + bAction *act= verify_adt_action((ID *)key, 1); + FCurve *fcu= verify_fcurve(act, NULL, rna_path, 0, 1); + + /* set the special 'replace' flag if on a keyframe */ + if (fcurve_frame_has_keyframe(fcu, cfra, 0)) + flag |= INSERTKEY_REPLACE; + + /* insert a keyframe for this F-Curve */ + done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag); + + if (done) + WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL); + } + + /* free the path */ + if (rna_path) + MEM_freeN(rna_path); +} /* Draw a widget for some setting */ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting) @@ -2445,7 +2558,7 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b * and wouldn't be able to auto-keyframe... * - slider should start before the toggles (if they're visible) to keep a clean line down the side */ - if ((draw_sliders) && (ale->type == ANIMTYPE_FCURVE)) { + if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) { /* adjust offset */ offset += SLIDER_WIDTH; @@ -2453,20 +2566,49 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b uiBlockSetEmboss(block, UI_EMBOSS); if (ale->id) { /* Slider using RNA Access -------------------- */ - FCurve *fcu= (FCurve *)ale->data; PointerRNA id_ptr, ptr; PropertyRNA *prop; + char *rna_path = NULL; + int array_index = 0; + short free_path = 0; - /* get RNA pointer, and resolve the path */ - RNA_id_pointer_create(ale->id, &id_ptr); + /* get destination info */ + if (ale->type == ANIMTYPE_FCURVE) { + FCurve *fcu= (FCurve *)ale->data; + + rna_path= fcu->rna_path; + array_index= fcu->array_index; + } + else if (ale->type == ANIMTYPE_SHAPEKEY) { + KeyBlock *kb= (KeyBlock *)ale->data; + Key *key= (Key *)ale->id; + + rna_path= key_get_curValue_rnaPath(key, kb); + free_path= 1; + } - /* try to resolve the path */ - if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) { - uiBut *but; + /* only if RNA-Path found */ + if (rna_path) { + /* get RNA pointer, and resolve the path */ + RNA_id_pointer_create(ale->id, &id_ptr); + + /* try to resolve the path */ + if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) { + uiBut *but; + + /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */ + but= uiDefAutoButR(block, &ptr, prop, array_index, "", 0, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc); + + /* assign keyframing function according to slider type */ + if (ale->type == ANIMTYPE_SHAPEKEY) + uiButSetFunc(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data); + else + uiButSetFunc(but, achannel_setting_slider_cb, ale->id, ale->data); + } - /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */ - but= uiDefAutoButR(block, &ptr, prop, fcu->array_index, "", 0, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc); - uiButSetFunc(but, achannel_setting_slider_cb, ale->id, fcu); + /* free the path if necessary */ + if (free_path) + MEM_freeN(rna_path); } } else { /* Special Slider for stuff without RNA Access ---------- */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 3b6c7fad471..efdad53f89f 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -238,6 +238,10 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short if (ale->flag & FCURVE_SELECTED) sel= ACHANNEL_SETFLAG_CLEAR; break; + case ANIMTYPE_SHAPEKEY: + if (ale->flag & KEYBLOCK_SEL) + sel= ACHANNEL_SETFLAG_CLEAR; + break; case ANIMTYPE_NLATRACK: if (ale->flag & NLATRACK_SELECTED) sel= ACHANNEL_SETFLAG_CLEAR; @@ -307,6 +311,13 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short fcu->flag &= ~FCURVE_ACTIVE; } break; + case ANIMTYPE_SHAPEKEY: + { + KeyBlock *kb= (KeyBlock *)ale->data; + + ACHANNEL_SET_FLAG(kb, sel, KEYBLOCK_SEL); + } + break; case ANIMTYPE_NLATRACK: { NlaTrack *nlt= (NlaTrack *)ale->data; @@ -1520,6 +1531,24 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh notifierFlags |= ND_ANIMCHAN_SELECT; } break; + case ANIMTYPE_SHAPEKEY: + { + KeyBlock *kb= (KeyBlock *)ale->data; + + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this ShapeKey only */ + kb->flag ^= KEYBLOCK_SEL; + } + else { + /* select ShapeKey by itself */ + ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + kb->flag |= KEYBLOCK_SEL; + } + + notifierFlags |= ND_ANIMCHAN_SELECT; + } + break; case ANIMTYPE_GPDATABLOCK: { bGPdata *gpd= (bGPdata *)ale->data; @@ -1557,9 +1586,6 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh #endif // XXX future of this is unclear } break; - case ANIMTYPE_SHAPEKEY: - /* TODO: shapekey channels cannot be selected atm... */ - break; default: printf("Error: Invalid channel type in mouse_anim_channels() \n"); } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index ea097420d1a..84da3662661 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -647,6 +647,36 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s ale->datatype= ALE_FCURVE; } break; + + case ANIMTYPE_SHAPEKEY: + { + KeyBlock *kb= (KeyBlock *)data; + Key *key= (Key *)ale->id; + + ale->flag= kb->flag; + + /* whether we have keyframes depends on whether there is a Key block to find it from */ + if (key) { + /* index of shapekey is defined by place in key's list */ + ale->index= BLI_findindex(&key->block, kb); + + /* the corresponding keyframes are from the animdata */ + if (ale->adt && ale->adt->action) { + bAction *act= ale->adt->action; + char *rna_path = key_get_curValue_rnaPath(key, kb); + + /* try to find the F-Curve which corresponds to this exactly, + * then free the MEM_alloc'd string + */ + if (rna_path) { + ale->key_data= list_find_fcurve(&act->curves, rna_path, 0); + MEM_freeN(rna_path); + } + } + ale->datatype= (ale->key_data)? ALE_FCURVE : ALE_NONE; + } + } + break; case ANIMTYPE_GPLAYER: { @@ -892,7 +922,51 @@ static int animdata_filter_nla (ListBase *anim_data, bDopeSheet *ads, AnimData * /* return the number of items added to the list */ return items; } - + +/* Include ShapeKey Data for ShapeKey Editor */ +static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode) +{ + int items = 0; + + /* check if channels or only F-Curves */ + if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) { + bAnimListElem *ale; + KeyBlock *kb; + + /* loop through the channels adding ShapeKeys as appropriate */ + for (kb= key->block.first; kb; kb= kb->next) { + /* skip the first one, since that's the non-animateable basis */ + // XXX maybe in future this may become handy? + if (kb == key->block.first) continue; + + /* only work with this channel and its subchannels if it is editable */ + if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) { + /* only include this track if selected in a way consistent with the filtering requirements */ + if ( ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb)) ) { + // TODO: consider 'active' too? + + /* owner-id here must be key so that the F-Curve can be resolved... */ + ale= make_new_animlistelem(kb, ANIMTYPE_SHAPEKEY, NULL, ANIMTYPE_NONE, (ID *)key); + + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + } + } + } + else { + /* just use the action associated with the shapekey */ + // FIXME: is owner-id and having no owner/dopesheet really fine? + if (key->adt && key->adt->action) + items= animdata_filter_action(anim_data, NULL, key->adt->action, filter_mode, NULL, ANIMTYPE_NONE, (ID *)key); + } + + /* return the number of items added to the list */ + return items; +} + #if 0 // FIXME: switch this to use the bDopeSheet... static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode) @@ -1944,9 +2018,11 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode } break; - case ANIMCONT_SHAPEKEY: + case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */ { - //items= animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact); + /* the check for the DopeSheet summary is included here since the summary works here too */ + if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) + items= animdata_filter_shapekey(anim_data, data, filter_mode); } break; diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 271827c2aba..316f1b58d33 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -99,7 +99,7 @@ typedef struct bAnimListElem { void *data; /* source data this elem represents */ int type; /* one of the ANIMTYPE_* values */ int flag; /* copy of elem's flags for quick access */ - int index; /* copy of adrcode where applicable */ + int index; /* for un-named data, the index of the data in it's collection */ void *key_data; /* motion data - mostly F-Curves, but can be other types too */ short datatype; /* type of motion data to expect */ @@ -144,7 +144,7 @@ typedef enum eAnim_ChannelType { ANIMTYPE_DSMBALL, ANIMTYPE_DSARM, - ANIMTYPE_SHAPEKEY, // XXX probably can become depreceated??? + ANIMTYPE_SHAPEKEY, ANIMTYPE_GPDATABLOCK, ANIMTYPE_GPLAYER, @@ -209,7 +209,7 @@ typedef enum eAnimFilter_Flags { #define FILTER_MAT_OBJC(ob) ((ob->nlaflag & OB_ADS_SHOWMATS)) #define FILTER_PART_OBJC(ob) ((ob->nlaflag & OB_ADS_SHOWPARTS)) /* 'Sub-object' channels (flags stored in Data block) */ -#define FILTER_SKE_OBJD(key) ((key->flag & KEYBLOCK_DS_EXPAND)) +#define FILTER_SKE_OBJD(key) ((key->flag & KEY_DS_EXPAND)) #define FILTER_MAT_OBJD(ma) ((ma->flag & MA_DS_EXPAND)) #define FILTER_LAM_OBJD(la) ((la->flag & LA_DS_EXPAND)) #define FILTER_CAM_OBJD(ca) ((ca->flag & CAM_DS_EXPAND)) @@ -232,6 +232,10 @@ typedef enum eAnimFilter_Flags { #define EDITABLE_FCU(fcu) ((fcu->flag & FCURVE_PROTECTED)==0) #define SEL_FCU(fcu) (fcu->flag & (FCURVE_ACTIVE|FCURVE_SELECTED)) +/* ShapeKey mode only */ +#define EDITABLE_SHAPEKEY(kb) ((kb->flag & KEYBLOCK_LOCKED)==0) +#define SEL_SHAPEKEY(kb) (kb->flag & KEYBLOCK_SEL) + /* Grease Pencil only */ /* Grease Pencil datablock settings */ #define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND) diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h index c42e555d562..e86abf12424 100644 --- a/source/blender/makesdna/DNA_key_types.h +++ b/source/blender/makesdna/DNA_key_types.h @@ -80,6 +80,7 @@ typedef struct Key { #define KEY_RELATIVE 1 /* key->flag */ +#define KEY_DS_EXPAND 1 /* keyblock->type */ #define KEY_LINEAR 0 @@ -87,8 +88,9 @@ typedef struct Key { #define KEY_BSPLINE 2 /* keyblock->flag */ -#define KEYBLOCK_MUTE 1 -#define KEYBLOCK_DS_EXPAND 2 +#define KEYBLOCK_MUTE (1<<0) +#define KEYBLOCK_SEL (1<<1) +#define KEYBLOCK_LOCKED (1<<2) #endif |