diff options
Diffstat (limited to 'source/blender/editors/animation/keyframing.c')
-rw-r--r-- | source/blender/editors/animation/keyframing.c | 255 |
1 files changed, 92 insertions, 163 deletions
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index d0675dc42ba..f60181d7f6c 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -40,15 +40,11 @@ #include "BLI_dynstr.h" #include "DNA_anim_types.h" -#include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_key_types.h" -#include "DNA_object_types.h" #include "DNA_material_types.h" #include "DNA_scene_types.h" -#include "DNA_userdef_types.h" -#include "DNA_windowmanager_types.h" #include "BKE_animsys.h" #include "BKE_action.h" @@ -67,7 +63,6 @@ #include "ED_keyframing.h" #include "ED_keyframes_edit.h" #include "ED_screen.h" -#include "ED_util.h" #include "UI_interface.h" @@ -76,7 +71,6 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_types.h" #include "anim_intern.h" @@ -136,8 +130,11 @@ bAction *verify_adt_action (ID *id, short add) /* init action if none available yet */ // TODO: need some wizardry to handle NLA stuff correct - if ((adt->action == NULL) && (add)) - adt->action= add_empty_action("Action"); + if ((adt->action == NULL) && (add)) { + char actname[sizeof(id->name)-2]; + BLI_snprintf(actname, sizeof(actname), "%sAction", id->name+2); + adt->action= add_empty_action(actname); + } /* return the action */ return adt->action; @@ -182,16 +179,8 @@ FCurve *verify_fcurve (bAction *act, const char group[], const char rna_path[], grp= action_groups_find_named(act, group); /* no matching groups, so add one */ - if (grp == NULL) { - /* Add a new group, and make it active */ - grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup"); - - grp->flag = AGRP_SELECTED; - strncpy(grp->name, group, sizeof(grp->name)); - - BLI_addtail(&act->groups, grp); - BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name)); - } + if (grp == NULL) + grp= action_groups_add_new(act, group); /* add F-Curve to group */ action_groups_add_channel(act, grp, fcu); @@ -231,27 +220,16 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag) if (replace) { /* sanity check: 'i' may in rare cases exceed arraylen */ if ((i >= 0) && (i < fcu->totvert)) { - /* take care with the handletypes and other info if the replacement flags are set */ - if (flag & INSERTKEY_REPLACE) { - BezTriple *dst= (fcu->bezt + i); - float dy= bezt->vec[1][1] - dst->vec[1][1]; - - /* just apply delta value change to the handle values */ - dst->vec[0][1] += dy; - dst->vec[1][1] += dy; - dst->vec[2][1] += dy; - - // TODO: perform some other operations? - } - else { - char oldKeyType= BEZKEYTYPE(fcu->bezt + i); - - /* just brutally replace the values */ - *(fcu->bezt + i) = *bezt; - - /* special exception for keyframe type - copy value back so that this info isn't lost */ - BEZKEYTYPE(fcu->bezt + i)= oldKeyType; - } + /* just change the values when replacing, so as to not overwrite handles */ + BezTriple *dst= (fcu->bezt + i); + float dy= bezt->vec[1][1] - dst->vec[1][1]; + + /* just apply delta value change to the handle values */ + dst->vec[0][1] += dy; + dst->vec[1][1] += dy; + dst->vec[2][1] += dy; + + // TODO: perform some other operations? } } /* keyframing modes allow to not replace keyframe */ @@ -259,14 +237,14 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag) /* insert new - if we're not restricted to replacing keyframes only */ BezTriple *newb= MEM_callocN((fcu->totvert+1)*sizeof(BezTriple), "beztriple"); - /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */ + /* add the beztriples that should occur before the beztriple to be pasted (originally in fcu) */ if (i > 0) memcpy(newb, fcu->bezt, i*sizeof(BezTriple)); /* add beztriple to paste at index i */ *(newb + i)= *bezt; - /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */ + /* add the beztriples that occur after the beztriple to be pasted (originally in fcu) */ if (i < fcu->totvert) memcpy(newb+i+1, fcu->bezt+i, (fcu->totvert-i)*sizeof(BezTriple)); @@ -311,17 +289,19 @@ int insert_vert_fcurve (FCurve *fcu, float x, float y, short flag) BezTriple beztr; int a; - /* set all three points, for nicer start position */ + /* set all three points, for nicer start position + * NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok... + */ memset(&beztr, 0, sizeof(BezTriple)); - beztr.vec[0][0]= x; + beztr.vec[0][0]= x-1.0f; beztr.vec[0][1]= y; beztr.vec[1][0]= x; beztr.vec[1][1]= y; - beztr.vec[2][0]= x; + beztr.vec[2][0]= x+1.0f; beztr.vec[2][1]= y; beztr.ipo= U.ipo_new; /* use default interpolation mode here... */ beztr.f1= beztr.f2= beztr.f3= SELECT; - beztr.h1= beztr.h2= HD_AUTO; // XXX what about when we replace an old one? + beztr.h1= beztr.h2= U.keyhandles_new; /* use default handle type here */ //BEZKEYTYPE(&beztr)= scene->keytype; /* default keyframe type */ /* add temp beztriple to keyframes */ @@ -342,18 +322,9 @@ int insert_vert_fcurve (FCurve *fcu, float x, float y, short flag) /* set handletype and interpolation */ if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE)==0) { BezTriple *bezt= (fcu->bezt + a); - char h1, h2; - - /* set handles (autohandles by default) */ - h1= h2= HD_AUTO; - - if (a > 0) h1= (bezt-1)->h2; - if (a < fcu->totvert-1) h2= (bezt+1)->h1; - - bezt->h1= h1; - bezt->h2= h2; /* set interpolation from previous (if available) */ + // FIXME: this doesn't work if user tweaked the interpolation specifically, and they were just overwriting some existing key in the process... if (a > 0) bezt->ipo= (bezt-1)->ipo; else if (a < fcu->totvert-1) bezt->ipo= (bezt+1)->ipo; @@ -846,15 +817,21 @@ short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, fl short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) { PointerRNA id_ptr, ptr; - PropertyRNA *prop; + PropertyRNA *prop = NULL; FCurve *fcu; int array_index_max= array_index+1; int ret= 0; /* validate pointer first - exit if failure */ + if (id == NULL) { + printf("Insert Key: no ID-block to insert keyframe in (Path = %s) \n", rna_path); + return 0; + } + RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { - printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); + printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", + (id)? id->name : "<Missing ID-Block>", rna_path); return 0; } @@ -903,21 +880,27 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_ /* will only loop once unless the array index was -1 */ for (; array_index < array_index_max; array_index++) { - /* make sure the F-Curve exists */ - fcu= verify_fcurve(act, group, rna_path, array_index, 1); + /* make sure the F-Curve exists + * - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet + * but still try to get the F-Curve if it exists... + */ + fcu= verify_fcurve(act, group, rna_path, array_index, (flag & INSERTKEY_REPLACE)==0); - /* set color mode if the F-Curve is new (i.e. without any keyframes) */ - if ((fcu->totvert == 0) && (flag & INSERTKEY_XYZ2RGB)) { - /* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor, - * is determined by the array index for the F-Curve - */ - if (ELEM4(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR)) { - fcu->color_mode= FCURVE_COLOR_AUTO_RGB; + /* we may not have a F-Curve when we're replacing only... */ + if (fcu) { + /* set color mode if the F-Curve is new (i.e. without any keyframes) */ + if ((fcu->totvert == 0) && (flag & INSERTKEY_XYZ2RGB)) { + /* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor, + * is determined by the array index for the F-Curve + */ + if (ELEM4(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR)) { + fcu->color_mode= FCURVE_COLOR_AUTO_RGB; + } } + + /* insert keyframe */ + ret += insert_keyframe_direct(ptr, prop, fcu, cfra, flag); } - - /* insert keyframe */ - ret += insert_keyframe_direct(ptr, prop, fcu, cfra, flag); } return ret; @@ -945,7 +928,7 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_ if ELEM(NULL, id, adt) { printf("ERROR: no ID-block and/or AnimData to delete keyframe from \n"); return 0; - } + } /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); @@ -1059,9 +1042,13 @@ static int modify_key_op_poll(bContext *C) if (ELEM(NULL, sa, scene)) return 0; - /* if Outliner, only allow in DataBlocks view */ - if (so && (so->outlinevis != SO_DATABLOCKS)) - return 0; + /* if Outliner, don't allow in some views */ + if (so) { + if (ELEM4(so->outlinevis, SO_GROUPS, SO_LIBRARIES, SO_VERSE_SESSION, SO_VERSE_SESSION)) + return 0; + if (ELEM3(so->outlinevis, SO_SEQUENCE, SO_USERDEF, SO_KEYMAP)) + return 0; + } /* TODO: checks for other space types can be added here */ @@ -1073,7 +1060,6 @@ static int modify_key_op_poll(bContext *C) static int insert_key_exec (bContext *C, wmOperator *op) { - ListBase dsources = {NULL, NULL}; Scene *scene= CTX_data_scene(C); KeyingSet *ks= NULL; int type= RNA_int_get(op->ptr, "type"); @@ -1098,38 +1084,26 @@ static int insert_key_exec (bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* get context info for relative Keying Sets */ - if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) { - /* exit if no suitable data obtained */ - if (modifykey_get_context_data(C, &dsources, ks) == 0) { - BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set"); - return OPERATOR_CANCELLED; - } - } - /* try to insert keyframes for the channels specified by KeyingSet */ - success= modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + success= ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); if (G.f & G_DEBUG) BKE_reportf(op->reports, RPT_INFO, "KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success); /* report failure or do updates? */ - if (success) { + if (success == MODIFYKEY_INVALID_CONTEXT) { + BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set"); + return OPERATOR_CANCELLED; + } + else if (success) { /* if the appropriate properties have been set, make a note that we've inserted something */ if (RNA_boolean_get(op->ptr, "confirm_success")) BKE_reportf(op->reports, RPT_INFO, "Successfully added %d Keyframes for KeyingSet '%s'", success, ks->name); /* send notifiers that keyframes have been changed */ - WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); } else BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes"); - - - /* free temp context-data if available */ - if (dsources.first) { - /* we assume that there is no extra data that needs to be freed from here... */ - BLI_freelistN(&dsources); - } /* send updates */ DAG_ids_flush_update(0); @@ -1139,6 +1113,8 @@ static int insert_key_exec (bContext *C, wmOperator *op) void ANIM_OT_keyframe_insert (wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name= "Insert Keyframe"; ot->idname= "ANIM_OT_keyframe_insert"; @@ -1154,60 +1130,20 @@ void ANIM_OT_keyframe_insert (wmOperatorType *ot) /* keyingset to use * - here the type is int not enum, since many of the indicies here are determined dynamically */ - RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1); + prop= RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1); + RNA_def_property_flag(prop, PROP_HIDDEN); /* confirm whether a keyframe was added by showing a popup * - by default, this is enabled, since this operator is assumed to be called independently */ - RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Insert", "Show a popup when the keyframes get successfully added"); + prop= RNA_def_boolean(ot->srna, "confirm_success", 1, "Confirm Successful Insert", "Show a popup when the keyframes get successfully added"); + RNA_def_property_flag(prop, PROP_HIDDEN); } /* Insert Key Operator (With Menu) ------------------------ */ /* This operator checks if a menu should be shown for choosing the KeyingSet to use, - * then calls the + * then calls the menu if necessary before */ -static void insert_key_menu_prompt (bContext *C) -{ - Scene *scene= CTX_data_scene(C); - KeyingSet *ks; - uiPopupMenu *pup; - uiLayout *layout; - int i = 0; - - pup= uiPupMenuBegin(C, "Insert Keyframe", 0); - layout= uiPupMenuLayout(pup); - - /* active Keying Set - * - only include entry if it exists - */ - if (scene->active_keyingset) { - uiItemIntO(layout, "Active Keying Set", 0, "ANIM_OT_keyframe_insert_menu", "type", i++); - uiItemS(layout); - } - else - i++; - - /* user-defined Keying Sets - * - these are listed in the order in which they were defined for the active scene - */ - if (scene->keyingsets.first) { - for (ks= scene->keyingsets.first; ks; ks= ks->next) - uiItemIntO(layout, ks->name, 0, "ANIM_OT_keyframe_insert_menu", "type", i++); - uiItemS(layout); - } - - /* builtin Keying Sets */ - i= -1; - for (ks= builtin_keyingsets.first; ks; ks= ks->next) { - /* only show KeyingSet if context is suitable */ - if (keyingset_context_ok_poll(C, ks)) { - uiItemIntO(layout, ks->name, 0, "ANIM_OT_keyframe_insert_menu", "type", i--); - } - } - - uiPupMenuEnd(C, pup); -} - static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *event) { Scene *scene= CTX_data_scene(C); @@ -1215,7 +1151,7 @@ static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *event) /* if prompting or no active Keying Set, show the menu */ if ((scene->active_keyingset == 0) || RNA_boolean_get(op->ptr, "always_prompt")) { /* call the menu, which will call this operator again, hence the cancelled */ - insert_key_menu_prompt(C); + ANIM_keying_sets_menu_setup(C, op->type->name, "ANIM_OT_keyframe_insert_menu"); return OPERATOR_CANCELLED; } else { @@ -1229,6 +1165,8 @@ static int insert_key_menu_invoke (bContext *C, wmOperator *op, wmEvent *event) void ANIM_OT_keyframe_insert_menu (wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name= "Insert Keyframe Menu"; ot->idname= "ANIM_OT_keyframe_insert_menu"; @@ -1244,24 +1182,26 @@ void ANIM_OT_keyframe_insert_menu (wmOperatorType *ot) /* keyingset to use * - here the type is int not enum, since many of the indicies here are determined dynamically */ - RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1); + prop= RNA_def_int(ot->srna, "type", 0, INT_MIN, INT_MAX, "Keying Set Number", "Index (determined internally) of the Keying Set to use", 0, 1); + RNA_def_property_flag(prop, PROP_HIDDEN); /* confirm whether a keyframe was added by showing a popup * - by default, this is disabled so that if a menu is shown, this doesn't come up too */ // XXX should this just be always on? - RNA_def_boolean(ot->srna, "confirm_success", 0, "Confirm Successful Insert", "Show a popup when the keyframes get successfully added"); + prop= RNA_def_boolean(ot->srna, "confirm_success", 0, "Confirm Successful Insert", "Show a popup when the keyframes get successfully added"); + RNA_def_property_flag(prop, PROP_HIDDEN); /* whether the menu should always be shown * - by default, the menu should only be shown when there is no active Keying Set (2.5 behaviour), * although in some cases it might be useful to always shown (pre 2.5 behaviour) */ - RNA_def_boolean(ot->srna, "always_prompt", 0, "Always Show Menu", ""); + prop= RNA_def_boolean(ot->srna, "always_prompt", 0, "Always Show Menu", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); } /* Delete Key Operator ------------------------ */ static int delete_key_exec (bContext *C, wmOperator *op) { - ListBase dsources = {NULL, NULL}; Scene *scene= CTX_data_scene(C); KeyingSet *ks= NULL; int type= RNA_int_get(op->ptr, "type"); @@ -1286,38 +1226,27 @@ static int delete_key_exec (bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* get context info for relative Keying Sets */ - if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) { - /* exit if no suitable data obtained */ - if (modifykey_get_context_data(C, &dsources, ks) == 0) { - BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set"); - return OPERATOR_CANCELLED; - } - } - /* try to insert keyframes for the channels specified by KeyingSet */ - success= modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_DELETE, cfra); + success= ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_DELETE, cfra); if (G.f & G_DEBUG) printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success); /* report failure or do updates? */ - if (success) { + if (success == MODIFYKEY_INVALID_CONTEXT) { + BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set"); + return OPERATOR_CANCELLED; + } + else if (success) { /* if the appropriate properties have been set, make a note that we've inserted something */ if (RNA_boolean_get(op->ptr, "confirm_success")) BKE_reportf(op->reports, RPT_INFO, "Successfully removed %d Keyframes for KeyingSet '%s'", success, ks->name); /* send notifiers that keyframes have been changed */ - WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); } else BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes"); - /* free temp context-data if available */ - if (dsources.first) { - /* we assume that there is no extra data that needs to be freed from here... */ - BLI_freelistN(&dsources); - } - /* send updates */ DAG_ids_flush_update(0); @@ -1474,7 +1403,7 @@ static int insert_key_button_exec (bContext *C, wmOperator *op) DAG_ids_flush_update(0); /* send notifiers that keyframes have been changed */ - WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); } return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; @@ -1544,7 +1473,7 @@ static int delete_key_button_exec (bContext *C, wmOperator *op) DAG_ids_flush_update(0); /* send notifiers that keyframes have been changed */ - WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); } return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; |