Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2010-03-16 09:18:49 +0300
committerJoshua Leung <aligorith@gmail.com>2010-03-16 09:18:49 +0300
commitea4a987fd424de77465f1a2cd95a655ccf42fd31 (patch)
treefe49fdb0e18ce012a3a366db7bed703635e0568c /source/blender/editors
parent604a2b1a1879c1e0ad1f637f5edc1ab12f61c31d (diff)
== Massive Keying Sets Recode ==
After a few days of wrong turns and learning the finer points of RNA-type-subclassing the hard way, this commit finally presents a refactored version of the Keying Sets system (now version 2) based on some requirements from Cessen. For a more thorough discussion of this commit, see http://sites.google.com/site/aligorith/keyingsets_2.pdf?attredirects=0&d=1 ------ The main highlight of this refactor is that relative Keying Sets have now been recoded so that Python callbacks are run to generate the Keying Set's list of paths everytime the Keying Set is used (to insert or delete keyframes), allowing complex heuristics to be used to determine whether a property gets keyframed based on the current context. These checks may include checking on selection status of related entities, or transform locks. Built-In KeyingSets have also been recoded, and moved from C and out into Python. These are now coded as Relative Keying Sets, and can to some extent serve as basis for adding new relative Keying Sets. However, these have mostly been coded in a slightly 'modular' way which may be confusing for those not so familiar with Python in general. A usable template will be added soon for more general usage. Keyframing settings (i.e. 'visual', 'needed') can now be specified on a per-path basis now, which is especially useful for Absolute Keying Sets, where control over this is often beneficial. Most of the places where Auto-Keyframing is performed have been tidied up for consistency. I'm sure quite a few issues still exist there, but these I'll clean up over the next few days.
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_intern.h6
-rw-r--r--source/blender/editors/animation/keyframing.c58
-rw-r--r--source/blender/editors/animation/keyingsets.c1143
-rw-r--r--source/blender/editors/armature/editarmature.c72
-rw-r--r--source/blender/editors/armature/poseUtils.c25
-rw-r--r--source/blender/editors/armature/poselib.c61
-rw-r--r--source/blender/editors/armature/poseobject.c129
-rw-r--r--source/blender/editors/include/ED_keyframing.h86
-rw-r--r--source/blender/editors/object/object_transform.c84
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c20
-rw-r--r--source/blender/editors/transform/transform_conversions.c90
11 files changed, 523 insertions, 1251 deletions
diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h
index 5602bff77ce..379b8c27de5 100644
--- a/source/blender/editors/animation/anim_intern.h
+++ b/source/blender/editors/animation/anim_intern.h
@@ -33,12 +33,6 @@
/* list of builtin KeyingSets (defined in keyingsets.c) */
extern ListBase builtin_keyingsets;
-/* for builtin keyingsets - context poll */
-short keyingset_context_ok_poll(bContext *C, KeyingSet *ks);
-
-/* Main KeyingSet operations API call */
-short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks);
-
/* Operator Define Prototypes ------------------- */
/* Main Keyframe Management operators:
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index d0675dc42ba..eaebab2efab 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1073,7 +1073,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,22 +1097,17 @@ 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);
@@ -1123,13 +1117,6 @@ static int insert_key_exec (bContext *C, wmOperator *op)
}
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);
@@ -1191,8 +1178,10 @@ static void insert_key_menu_prompt (bContext *C)
* - 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++);
+ for (ks= scene->keyingsets.first; ks; ks= ks->next) {
+ if (ANIM_keyingset_context_ok_poll(C, ks))
+ uiItemIntO(layout, ks->name, 0, "ANIM_OT_keyframe_insert_menu", "type", i++);
+ }
uiItemS(layout);
}
@@ -1200,9 +1189,8 @@ static void insert_key_menu_prompt (bContext *C)
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)) {
+ if (ANIM_keyingset_context_ok_poll(C, ks))
uiItemIntO(layout, ks->name, 0, "ANIM_OT_keyframe_insert_menu", "type", i--);
- }
}
uiPupMenuEnd(C, pup);
@@ -1261,7 +1249,6 @@ void ANIM_OT_keyframe_insert_menu (wmOperatorType *ot)
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,22 +1273,17 @@ 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);
@@ -1312,12 +1294,6 @@ static int delete_key_exec (bContext *C, wmOperator *op)
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);
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 63323a8519d..1e4180a3ae7 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -256,14 +256,8 @@ static int remove_active_ks_path_exec (bContext *C, wmOperator *op)
KS_Path *ksp= BLI_findlink(&ks->paths, ks->active_path-1);
if (ksp) {
- /* NOTE: sync this code with BKE_keyingset_free() */
- {
- /* free RNA-path info */
- MEM_freeN(ksp->rna_path);
-
- /* free path itself */
- BLI_freelinkN(&ks->paths, ksp);
- }
+ /* remove the active path from the KeyingSet */
+ BKE_keyingset_free_path(ks, ksp);
/* the active path should now be the previously second-to-last active one */
ks->active_path--;
@@ -467,663 +461,136 @@ void ANIM_OT_keyingset_button_remove (wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-/* ************************************************** */
-/* KEYING SETS - EDITING API */
-
-/* UI API --------------------------------------------- */
-
-/* Build menu-string of available keying-sets (allocates memory for string)
- * NOTE: mode must not be longer than 64 chars
- */
-char *ANIM_build_keyingsets_menu (ListBase *list, short for_edit)
-{
- DynStr *pupds= BLI_dynstr_new();
- KeyingSet *ks;
- char buf[64];
- char *str;
- int i;
-
- /* add title first */
- BLI_dynstr_append(pupds, "Keying Sets%t|");
-
- /* add dummy entries for none-active */
- if (for_edit) {
- BLI_dynstr_append(pupds, "Add New%x-1|");
- BLI_dynstr_append(pupds, " %x0|");
- }
- else
- BLI_dynstr_append(pupds, "No Keying Set%x0|");
-
- /* loop through keyingsets, adding them */
- for (ks=list->first, i=1; ks; ks=ks->next, i++) {
- if (for_edit == 0)
- BLI_dynstr_append(pupds, "KS: ");
-
- BLI_dynstr_append(pupds, ks->name);
- BLI_snprintf( buf, 64, "%%x%d%s", i, ((ks->next)?"|":"") );
- BLI_dynstr_append(pupds, buf);
- }
-
- /* convert to normal MEM_malloc'd string */
- str= BLI_dynstr_get_cstring(pupds);
- BLI_dynstr_free(pupds);
-
- return str;
-}
-
-
/* ******************************************* */
-/* KEYING SETS - BUILTIN */
-
-#if 0 // XXX old keyingsets code based on adrcodes... to be restored in due course
-
-/* ------------- KeyingSet Defines ------------ */
-/* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */
-
-/* macro for defining keyingset contexts */
-#define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)}
+/* REGISTERED KEYING SETS */
-/* --- */
+/* Keying Set Type Info declarations */
+ListBase keyingset_type_infos = {NULL, NULL};
-/* check if option not available for deleting keys */
-static short incl_non_del_keys (bKeyingSet *ks, const char mode[])
-{
- /* as optimisation, assume that it is sufficient to check only first letter
- * of mode (int comparison should be faster than string!)
- */
- //if (strcmp(mode, "Delete")==0)
- if (mode && mode[0]=='D')
- return 0;
-
- return 1;
-}
+/* Built-In Keying Sets (referencing type infos)*/
+ListBase builtin_keyingsets = {NULL, NULL};
-/* Object KeyingSets ------ */
+/* --------------- */
-/* check if include shapekey entry */
-static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
+/* Find KeyingSet type info given a name */
+KeyingSetInfo *ANIM_keyingset_info_find_named (const char name[])
{
- //Object *ob= (G.obedit)? (G.obedit) : (OBACT); // XXX
- Object *ob= NULL;
- char *newname= NULL;
-
- if(ob==NULL)
- return 0;
-
- /* not available for delete mode */
- if (strcmp(mode, "Delete")==0)
- return 0;
+ KeyingSetInfo *ksi;
- /* check if is geom object that can get shapekeys */
- switch (ob->type) {
- /* geometry? */
- case OB_MESH: newname= "Mesh"; break;
- case OB_CURVE: newname= "Curve"; break;
- case OB_SURF: newname= "Surface"; break;
- case OB_LATTICE: newname= "Lattice"; break;
+ /* sanity checks */
+ if ((name == NULL) || (name[0] == 0))
+ return NULL;
- /* not geometry! */
- default:
- return 0;
+ /* search by comparing names */
+ for (ksi = keyingset_type_infos.first; ksi; ksi = ksi->next) {
+ if (strcmp(ksi->name, name) == 0)
+ return ksi;
}
- /* if ks is shapekey entry (this could be callled for separator before too!) */
- if (ks->flag == -3)
- BLI_strncpy(ks->name, newname, sizeof(ks->name));
-
- /* if it gets here, it's ok */
- return 1;
+ /* no matches found */
+ return NULL;
}
-/* array for object keyingset defines */
-bKeyingSet defks_v3d_object[] =
-{
- /* include_cb, adrcode-getter, name, blocktype, flag, chan_num, adrcodes */
- {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
- {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
- {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "LocRot", ID_OB, 0, 6,
- {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
- OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
-
- {NULL, "LocScale", ID_OB, 0, 6,
- {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
- OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
-
- {NULL, "LocRotScale", ID_OB, 0, 9,
- {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
- OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
- OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
-
- {NULL, "RotScale", ID_OB, 0, 6,
- {OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
- OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
-
- {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
-
- {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
- {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
-
- {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6,
- {OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
- OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option...
- {NULL, "Available", ID_OB, -2, 0, {0}},
-
- {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry)
- {incl_v3d_ob_shapekey, "<ShapeKey>", ID_OB, -3, 0, {0}}
-};
-
-/* PoseChannel KeyingSets ------ */
-
-/* array for posechannel keyingset defines */
-bKeyingSet defks_v3d_pchan[] =
+/* Find builtin KeyingSet by name */
+KeyingSet *ANIM_builtin_keyingset_get_named (KeyingSet *prevKS, const char name[])
{
- /* include_cb, name, blocktype, flag, chan_num, adrcodes */
- {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
- {NULL, "Rot", ID_PO, COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
- {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "LocRot", ID_PO, COMMONKEY_PCHANROT, 4,
- {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
- KAG_CHAN_EXTEND}},
-
- {NULL, "LocScale", ID_PO, 0, 6,
- {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
- AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
-
- {NULL, "LocRotScale", ID_PO, COMMONKEY_PCHANROT, 7,
- {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z,
- KAG_CHAN_EXTEND}},
-
- {NULL, "RotScale", ID_PO, 0, 4,
- {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z,
- KAG_CHAN_EXTEND}},
-
- {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
-
- {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
- {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 1, {KAG_CHAN_EXTEND}},
-
- {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX|COMMONKEY_PCHANROT, 4,
- {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, KAG_CHAN_EXTEND}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Available", ID_PO, -2, 0, {0}}
-};
-
-/* Material KeyingSets ------ */
-
-/* array for material keyingset defines */
-bKeyingSet defks_buts_shading_mat[] =
-{
- /* include_cb, name, blocktype, flag, chan_num, adrcodes */
- {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}},
- {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}},
- {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}},
- {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "All Color", ID_MA, 0, 18,
- {MA_COL_R,MA_COL_G,MA_COL_B,
- MA_ALPHA,MA_HASIZE, MA_MODE,
- MA_SPEC_R,MA_SPEC_G,MA_SPEC_B,
- MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD,
- MA_MODE,MA_TRANSLU,MA_ADD}},
-
- {NULL, "All Mirror", ID_MA, 0, 5,
- {MA_RAYM,MA_FRESMIR,MA_FRESMIRI,
- MA_FRESTRA,MA_FRESTRAI}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Ofs", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
- {NULL, "Size", ID_MA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
-
- {NULL, "All Mapping", ID_MA, COMMONKEY_ADDMAP, 14,
- {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
- MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
- MAP_R,MAP_G,MAP_B,MAP_DVAR,
- MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Available", ID_MA, -2, 0, {0}}
-};
-
-/* World KeyingSets ------ */
-
-/* array for world keyingset defines */
-bKeyingSet defks_buts_shading_wo[] =
-{
- /* include_cb, name, blocktype, flag, chan_num, adrcodes */
- {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}},
- {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}},
- {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}},
-
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Ofs", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
- {NULL, "Size", ID_WO, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
-
- {NULL, "All Mapping", ID_WO, COMMONKEY_ADDMAP, 14,
- {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
- MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
- MAP_R,MAP_G,MAP_B,MAP_DVAR,
- MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Available", ID_WO, -2, 0, {0}}
-};
-
-/* Lamp KeyingSets ------ */
-
-/* array for lamp keyingset defines */
-bKeyingSet defks_buts_shading_la[] =
-{
- /* include_cb, name, blocktype, flag, chan_num, adrcodes */
- {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}},
- {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}},
- {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Ofs", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
- {NULL, "Size", ID_LA, COMMONKEY_ADDMAP, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
-
- {NULL, "All Mapping", ID_LA, COMMONKEY_ADDMAP, 14,
- {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
- MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
- MAP_R,MAP_G,MAP_B,MAP_DVAR,
- MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
+ KeyingSet *ks, *first=NULL;
- {NULL, "%l", 0, -1, 0, {0}}, // separator
+ /* sanity checks any name to check? */
+ if (name[0] == 0)
+ return NULL;
- {NULL, "Available", ID_LA, -2, 0, {0}}
-};
-
-/* Texture KeyingSets ------ */
-
-/* array for texture keyingset defines */
-bKeyingSet defks_buts_shading_tex[] =
-{
- /* include_cb, name, blocktype, flag, chan_num, adrcodes */
- {NULL, "Clouds", ID_TE, 0, 5,
- {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
- TE_MG_TYP,TE_N_BAS1}},
-
- {NULL, "Marble", ID_TE, 0, 7,
- {TE_NSIZE,TE_NDEPTH,TE_NTYPE,
- TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
-
- {NULL, "Stucci", ID_TE, 0, 5,
- {TE_NSIZE,TE_NTYPE,TE_TURB,
- TE_MG_TYP,TE_N_BAS1}},
-
- {NULL, "Wood", ID_TE, 0, 6,
- {TE_NSIZE,TE_NTYPE,TE_TURB,
- TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
-
- {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}},
-
- {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}},
-
- {NULL, "Musgrave", ID_TE, 0, 6,
- {TE_MG_TYP,TE_MGH,TE_MG_LAC,
- TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}},
-
- {NULL, "Voronoi", ID_TE, 0, 9,
- {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4,
- TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT,
- TE_ISCA,TE_NSIZE}},
+ /* get first KeyingSet to use */
+ if (prevKS && prevKS->next)
+ first= prevKS->next;
+ else
+ first= builtin_keyingsets.first;
- {NULL, "Distorted Noise", ID_TE, 0, 4,
- {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}},
-
- {NULL, "Color Filter", ID_TE, 0, 5,
- {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Available", ID_TE, -2, 0, {0}}
-};
-
-/* Object Buttons KeyingSets ------ */
-
-/* check if include particles entry */
-static short incl_buts_ob (bKeyingSet *ks, const char mode[])
-{
- //Object *ob= OBACT; // xxx
- Object *ob= NULL;
- /* only if object is mesh type */
-
- if(ob==NULL) return 0;
- return (ob->type == OB_MESH);
-}
-
-/* array for texture keyingset defines */
-bKeyingSet defks_buts_object[] =
-{
- /* include_cb, name, blocktype, flag, chan_num, adrcodes */
- {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}},
- {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}},
- {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
-
- {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}},
- {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
+ /* loop over KeyingSets checking names */
+ for (ks= first; ks; ks= ks->next) {
+ if (strcmp(name, ks->name) == 0)
+ return ks;
+ }
- {NULL, "Available", ID_OB, -2, 0, {0}} // this will include ob-transforms too!
-};
-
-/* Camera Buttons KeyingSets ------ */
-
-/* check if include internal-renderer entry */
-static short incl_buts_cam1 (bKeyingSet *ks, const char mode[])
-{
- Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
- /* only if renderer is internal renderer */
- return (scene->r.renderer==R_INTERN);
+ /* no matches found */
+ return NULL;
}
-/* check if include external-renderer entry */
-static short incl_buts_cam2 (bKeyingSet *ks, const char mode[])
-{
- Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first!
- /* only if renderer is internal renderer */
- return (scene->r.renderer!=R_INTERN);
-}
+/* --------------- */
-/* array for camera keyingset defines */
-bKeyingSet defks_buts_cam[] =
+/* Add the given KeyingSetInfo to the list of type infos, and create an appropriate builtin set too */
+void ANIM_keyingset_info_register (const bContext *C, KeyingSetInfo *ksi)
{
- /* include_cb, name, blocktype, flag, chan_num, adrcodes */
- {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}},
- {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}},
- {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}},
-
- {NULL, "%l", 0, -1, 0, {0}}, // separator
+ Scene *scene = CTX_data_scene(C);
+ ListBase *list = NULL;
+ KeyingSet *ks;
+ /* determine the KeyingSet list to include the new KeyingSet in */
+ if (ksi->builtin)
+ list = &builtin_keyingsets;
+ else
+ list = &scene->keyingsets;
- {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}},
- {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}},
+ /* create a new KeyingSet
+ * - inherit name and keyframing settings from the typeinfo
+ */
+ ks = BKE_keyingset_add(list, ksi->name, ksi->builtin, ksi->keyingflag);
- {NULL, "%l", 0, -1, 0, {0}}, // separator
+ /* link this KeyingSet with its typeinfo */
+ memcpy(&ks->typeinfo, ksi->name, sizeof(ks->typeinfo));
- {NULL, "Available", ID_CA, -2, 0, {0}}
-};
-
-/* --- */
+ /* add type-info to the list */
+ BLI_addtail(&keyingset_type_infos, ksi);
+}
-/* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
-bKeyingContext ks_contexts[] =
+/* Remove the given KeyingSetInfo from the list of type infos, and also remove the builtin set if appropriate */
+void ANIM_keyingset_info_unregister (const bContext *C, KeyingSetInfo *ksi)
{
- KSC_TEMPLATE(v3d_object),
- KSC_TEMPLATE(v3d_pchan),
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks, *ksn;
- KSC_TEMPLATE(buts_shading_mat),
- KSC_TEMPLATE(buts_shading_wo),
- KSC_TEMPLATE(buts_shading_la),
- KSC_TEMPLATE(buts_shading_tex),
-
- KSC_TEMPLATE(buts_object),
- KSC_TEMPLATE(buts_cam)
-};
-
-/* Keying Context Enumeration - Must keep in sync with definitions*/
-typedef enum eKS_Contexts {
- KSC_V3D_OBJECT = 0,
- KSC_V3D_PCHAN,
-
- KSC_BUTS_MAT,
- KSC_BUTS_WO,
- KSC_BUTS_LA,
- KSC_BUTS_TEX,
-
- KSC_BUTS_OB,
- KSC_BUTS_CAM,
-
- /* make sure this last one remains untouched! */
- KSC_TOT_TYPES
-} eKS_Contexts;
-
-
-#endif // XXX old keyingsets code based on adrcodes... to be restored in due course
-
-/* Macros for Declaring KeyingSets ------------------- */
-
-/* A note about this system for declaring built-in Keying Sets:
- * One may ask, "What is the purpose of all of these macros and static arrays?" and
- * "Why not call the KeyingSets API defined in BKE_animsys.h?". The answer is two-fold.
- *
- * 1) Firstly, we use static arrays of struct definitions instead of function calls, as
- * it reduces the start-up overhead and allocated-memory footprint of Blender. If we called
- * the KeyingSets API to build these sets, the overhead of checking for unique names, allocating
- * memory for each and every path and KeyingSet, scattered around in RAM, all of which would increase
- * the startup time (which is totally unacceptable) and could lead to fragmentation+slower access times.
- * 2) Since we aren't using function calls, we need a nice way of defining these KeyingSets in a way which
- * is easily readable and less prone to breakage from changes to the underlying struct definitions. Further,
- * adding additional entries SHOULD NOT require custom code to be written to access these new entries/sets.
- * Therefore, here we have a system with nice, human-readable statements via macros, and static arrays which
- * are linked together using more special macros + struct definitions, allowing for such a generic + simple
- * initialisation function (init_builtin_keyingsets()) compared with that of something like the Nodes system.
- *
- * -- Joshua Leung, April 2009
- */
-
-/* Struct type for declaring builtin KeyingSets in as entries in static arrays*/
-typedef struct bBuiltinKeyingSet {
- KeyingSet ks; /* the KeyingSet to build */
- int tot; /* the total number of paths defined */
- KS_Path paths[64]; /* the paths for the KeyingSet to use */
-} bBuiltinKeyingSet;
-
- /* WARNING: the following macros must be kept in sync with the
- * struct definitions in DNA_anim_types.h!
- */
-
-/* macro for defining a builtin KeyingSet */
-#define BI_KS_DEFINE_BEGIN(name, keyingflag) \
- {{NULL, NULL, {NULL, NULL}, name, KEYINGSET_BUILTIN, keyingflag},
-
-/* macro to finish defining a builtin KeyingSet */
-#define BI_KS_DEFINE_END \
- }
-
-/* macro to start defining paths for a builtin KeyingSet */
-#define BI_KS_PATHS_BEGIN(tot) \
- tot, {
-
-/* macro to finish defining paths for a builtin KeyingSet */
-#define BI_KS_PATHS_END \
+ /* find relevant scene KeyingSets which use this, and remove them */
+ for (ks= scene->keyingsets.first; ks; ks= ksn) {
+ ksn = ks->next;
+
+ /* remove if matching typeinfo name */
+ if (strcmp(ks->typeinfo, ksi->name) == 0) {
+ BKE_keyingset_free(ks);
+ BLI_freelinkN(&scene->keyingsets, ks);
+ }
}
-/* macro for defining a builtin KeyingSet's path */
-#define BI_KSP_DEFINE(id_type, templates, prop_path, array_index, flag, groupflag) \
- {NULL, NULL, NULL, "", id_type, templates, prop_path, array_index, flag, groupflag}
+ /* do the same with builtin sets? */
+ // TODO: this isn't done now, since unregister is really only used atm when we
+ // reload the scripts, which kindof defeats the purpose of "builtin"?
-/* macro for defining a builtin KeyingSet with no paths (use in place of BI_KS_PAHTS_BEGIN/END block) */
-#define BI_KS_PATHS_NONE \
- 0, {0}
-/* ---- */
-
-/* Struct type for finding all the arrays of builtin KeyingSets */
-typedef struct bBuiltinKSContext {
- bBuiltinKeyingSet *bks; /* array of KeyingSet definitions */
- int tot; /* number of KeyingSets in this array */
-} bBuiltinKSContext;
-
-/* macro for defining builtin KeyingSet sets
- * NOTE: all the arrays of sets must follow this naming convention!
- */
-#define BKSC_TEMPLATE(ctx_name) {&def_builtin_keyingsets_##ctx_name[0], sizeof(def_builtin_keyingsets_##ctx_name)/sizeof(bBuiltinKeyingSet)}
-
-
-/* 3D-View Builtin KeyingSets ------------------------ */
-
-static bBuiltinKeyingSet def_builtin_keyingsets_v3d[] =
-{
- /* Simple Keying Sets ************************************* */
- /* Keying Set - "Location" ---------- */
- BI_KS_DEFINE_BEGIN("Location", 0)
- BI_KS_PATHS_BEGIN(1)
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
- BI_KS_PATHS_END
- BI_KS_DEFINE_END,
-
- /* Keying Set - "Rotation" ---------- */
- BI_KS_DEFINE_BEGIN("Rotation", 0)
- BI_KS_PATHS_BEGIN(1)
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
- BI_KS_PATHS_END
- BI_KS_DEFINE_END,
-
- /* Keying Set - "Scaling" ---------- */
- BI_KS_DEFINE_BEGIN("Scaling", 0)
- BI_KS_PATHS_BEGIN(1)
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
- BI_KS_PATHS_END
- BI_KS_DEFINE_END,
-
- /* Compound Keying Sets *********************************** */
- /* Keying Set - "LocRot" ---------- */
- BI_KS_DEFINE_BEGIN("LocRot", 0)
- BI_KS_PATHS_BEGIN(2)
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM),
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
- BI_KS_PATHS_END
- BI_KS_DEFINE_END,
-
- /* Keying Set - "LocRotScale" ---------- */
- BI_KS_DEFINE_BEGIN("LocRotScale", 0)
- BI_KS_PATHS_BEGIN(3)
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM),
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM),
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
- BI_KS_PATHS_END
- BI_KS_DEFINE_END,
-
- /* Keying Sets with Keying Flags ************************* */
- /* Keying Set - "VisualLoc" ---------- */
- BI_KS_DEFINE_BEGIN("VisualLoc", INSERTKEY_MATRIX)
- BI_KS_PATHS_BEGIN(1)
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
- BI_KS_PATHS_END
- BI_KS_DEFINE_END,
-
- /* Keying Set - "Rotation" ---------- */
- BI_KS_DEFINE_BEGIN("VisualRot", INSERTKEY_MATRIX)
- BI_KS_PATHS_BEGIN(1)
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
- BI_KS_PATHS_END
- BI_KS_DEFINE_END,
-
- /* Keying Set - "VisualLocRot" ---------- */
- BI_KS_DEFINE_BEGIN("VisualLocRot", INSERTKEY_MATRIX)
- BI_KS_PATHS_BEGIN(2)
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM),
- BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM)
- BI_KS_PATHS_END
- BI_KS_DEFINE_END
-};
-
-/* All Builtin KeyingSets ------------------------ */
-
-/* total number of builtin KeyingSet contexts */
-#define MAX_BKSC_TYPES 1
-
-/* array containing all the available builtin KeyingSets definition sets
- * - size of this is MAX_BKSC_TYPES+1 so that we don't smash the stack
- */
-static bBuiltinKSContext def_builtin_keyingsets[MAX_BKSC_TYPES+1] =
-{
- BKSC_TEMPLATE(v3d)
- /* add more contexts above this line... */
-};
-
-
-/* ListBase of these KeyingSets chained up ready for usage
- * NOTE: this is exported to keyframing.c for use...
- */
-ListBase builtin_keyingsets = {NULL, NULL};
-
-/* Utility API ------------------------ */
-
-/* Link up all of the builtin Keying Sets when starting up Blender
- * This is called from WM_init() in wm_init_exit.c
- */
-void init_builtin_keyingsets (void)
-{
- bBuiltinKSContext *bksc;
- bBuiltinKeyingSet *bks;
- int bksc_i, bks_i;
-
- /* loop over all the sets of KeyingSets, setting them up, and chaining them to the builtins list */
- for (bksc_i= 0, bksc= &def_builtin_keyingsets[0]; bksc_i < MAX_BKSC_TYPES; bksc_i++, bksc++)
- {
- /* for each set definitions for a builtin KeyingSet, chain the paths to that KeyingSet and add */
- for (bks_i= 0, bks= bksc->bks; bks_i < bksc->tot; bks_i++, bks++)
- {
- KeyingSet *ks= &bks->ks;
- KS_Path *ksp;
- int pIndex;
-
- /* loop over paths, linking them to the KeyingSet and each other */
- for (pIndex= 0, ksp= &bks->paths[0]; pIndex < bks->tot; pIndex++, ksp++)
- BLI_addtail(&ks->paths, ksp);
-
- /* add KeyingSet to builtin sets list */
- BLI_addtail(&builtin_keyingsets, ks);
- }
- }
+ /* free the type info */
+ BLI_freelinkN(&keyingset_type_infos, ksi);
}
+/* --------------- */
-/* Get the first builtin KeyingSet with the given name, which occurs after the given one (or start of list if none given) */
-KeyingSet *ANIM_builtin_keyingset_get_named (KeyingSet *prevKS, char name[])
+void ANIM_keyingset_infos_exit ()
{
- KeyingSet *ks, *first=NULL;
-
- /* sanity checks - any name to check? */
- if (name[0] == 0)
- return NULL;
+ KeyingSetInfo *ksi, *next;
- /* get first KeyingSet to use */
- if (prevKS && prevKS->next)
- first= prevKS->next;
- else
- first= builtin_keyingsets.first;
+ /* free type infos */
+ for (ksi=keyingset_type_infos.first; ksi; ksi=next) {
+ next= ksi->next;
- /* loop over KeyingSets checking names */
- for (ks= first; ks; ks= ks->next) {
- if (strcmp(name, ks->name) == 0)
- return ks;
+ /* free extra RNA data, and remove from list */
+ if (ksi->ext.free)
+ ksi->ext.free(ksi->ext.data);
+ BLI_freelinkN(&keyingset_type_infos, ksi);
}
- /* no matches found */
- return NULL;
+ /* free builtin sets */
+ BKE_keyingsets_free(&builtin_keyingsets);
}
+/* ******************************************* */
+/* KEYING SETS API (for UI) */
/* Get the active Keying Set for the Scene provided */
KeyingSet *ANIM_scene_get_active_keyingset (Scene *scene)
@@ -1142,127 +609,74 @@ KeyingSet *ANIM_scene_get_active_keyingset (Scene *scene)
return NULL;
}
-/* ******************************************* */
-/* KEYFRAME MODIFICATION */
-
-/* KeyingSet Menu Helpers ------------ */
-
-/* Extract the maximum set of requirements from the KeyingSet */
-static int keyingset_relative_get_templates (KeyingSet *ks)
+/* Check if KeyingSet can be used in the current context */
+short ANIM_keyingset_context_ok_poll (bContext *C, KeyingSet *ks)
{
- KS_Path *ksp;
- int templates= 0;
-
- /* loop over the paths (could be slow to do for a number of KeyingSets)? */
- for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
- /* add the destination's templates to the set of templates required for the set */
- templates |= ksp->templates;
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
+ KeyingSetInfo *ksi = ANIM_keyingset_info_find_named(ks->typeinfo);
+
+ /* get the associated 'type info' for this KeyingSet */
+ if (ksi == NULL)
+ return 0;
+ // TODO: check for missing callbacks!
+
+ /* check if it can be used in the current context */
+ return (ksi->poll(ksi, C));
}
- return templates;
-}
-
-/* Check if context data is suitable for the given Keying Set */
-short keyingset_context_ok_poll (bContext *C, KeyingSet *ks)
-{
- // TODO:
- // For 'relative' keyingsets (i.e. py-keyingsets), add a call here
- // which basically gets a listing of all the paths to be used for this
- // set.
-
-
return 1;
}
-/* KeyingSet Context Operations ------------ */
+/* ******************************************* */
+/* KEYFRAME MODIFICATION */
+
+/* Special 'Overrides' Iterator for Relative KeyingSets ------ */
+
+/* 'Data Sources' for relative Keying Set 'overrides'
+ * - this is basically a wrapper for PointerRNA's in a linked list
+ * - do not allow this to be accessed from outside for now
+ */
+typedef struct tRKS_DSource {
+ struct tRKS_DSource *next, *prev;
+ PointerRNA ptr; /* the whole point of this exercise! */
+} tRKS_DSource;
+
-/* Get list of data-sources from context (in 3D-View) for inserting keyframes using the given relative Keying Set */
-static short modifykey_get_context_v3d_data (bContext *C, ListBase *dsources, KeyingSet *ks)
+/* Iterator used for overriding the behaviour of iterators defined for
+ * relative Keying Sets, with the main usage of this being operators
+ * requiring Auto Keyframing. Internal Use Only!
+ */
+static void RKS_ITER_overrides_list (KeyingSetInfo *ksi, bContext *C, KeyingSet *ks, ListBase *dsources)
{
- bCommonKeySrc *cks;
- Object *obact= CTX_data_active_object(C);
- int templates;
- short ok= 0;
-
- /* get the templates in use in this KeyingSet which we should supply data for */
- templates = keyingset_relative_get_templates(ks);
-
- /* check if the active object is in PoseMode (i.e. only deal with bones) */
- // TODO: check with the templates to see what we really need to store
- if ((obact && obact->pose) && (obact->mode & OB_MODE_POSE)) {
- /* Pose Mode: Selected bones */
-#if 0
- //set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */
-
- /* loop through posechannels */
- //for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
- // if (pchan->flag & POSE_KEY) {
- // }
- //}
-#endif
-
- CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
- {
- /* add a new keying-source */
- cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
- BLI_addtail(dsources, cks);
-
- /* set necessary info */
- cks->id= &obact->id;
- cks->pchan= pchan;
-
- if (templates & KSP_TEMPLATE_CONSTRAINT)
- cks->con= constraints_get_active(&pchan->constraints);
-
- ok= 1;
- }
- CTX_DATA_END;
- }
- else {
- /* Object Mode: Selected objects */
- CTX_DATA_BEGIN(C, Object*, ob, selected_objects)
- {
- /* add a new keying-source */
- cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
- BLI_addtail(dsources, cks);
-
- /* set necessary info */
- cks->id= &ob->id;
-
- if (templates & KSP_TEMPLATE_CONSTRAINT)
- cks->con= constraints_get_active(&ob->constraints);
-
- ok= 1;
- }
- CTX_DATA_END;
- }
+ tRKS_DSource *ds;
- /* return whether any data was extracted */
- return ok;
+ for (ds = dsources->first; ds; ds = ds->next) {
+ /* run generate callback on this data */
+ ksi->generate(ksi, C, ks, &ds->ptr);
+ }
}
-/* Get list of data-sources from context for inserting keyframes using the given relative Keying Set */
-short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks)
+/* Add new data source for relative Keying Sets */
+void ANIM_relative_keyingset_add_source (ListBase *dsources, ID *id, StructRNA *srna, void *data)
{
- ScrArea *sa= CTX_wm_area(C);
+ tRKS_DSource *ds;
- /* for now, the active area is used to determine what set of contexts apply */
- if (sa == NULL)
- return 0;
+ /* sanity checks
+ * we must have at least one valid data pointer to use
+ */
+ if (ELEM(NULL, dsources, srna) || ((id == data) && (id == NULL)))
+ return;
-#if 0
- switch (sa->spacetype) {
- case SPACE_VIEW3D: /* 3D-View: Selected Objects or Bones */
- return modifykey_get_context_v3d_data(C, dsources, ks);
- }
+ /* allocate new elem, and add to the list */
+ ds = MEM_callocN(sizeof(tRKS_DSource), "tRKS_DSource");
+ BLI_addtail(dsources, ds);
- /* nothing happened */
- return 0;
-#endif
-
- /* looking into this code, it doesnt use the 3D view - Campbell */
- return modifykey_get_context_v3d_data(C, dsources, ks);
-}
+ /* depending on what data we have, create using ID or full pointer call */
+ if (srna && data)
+ RNA_pointer_create(id, srna, data, &ds->ptr);
+ else
+ RNA_id_pointer_create(id, &ds->ptr);
+}
/* KeyingSet Operations (Insert/Delete Keyframes) ------------ */
@@ -1270,8 +684,9 @@ short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks
* by the KeyingSet. This takes into account many of the different combinations of using KeyingSets.
* Returns the number of channels that keyframes were added to
*/
-int modify_keyframes (Scene *scene, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
+int ANIM_apply_keyingset (bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
{
+ Scene *scene= CTX_data_scene(C);
KS_Path *ksp;
int kflag=0, success= 0;
char *groupname= NULL;
@@ -1291,201 +706,101 @@ int modify_keyframes (Scene *scene, ListBase *dsources, bAction *act, KeyingSet
else if (mode == MODIFYKEY_MODE_DELETE)
kflag= 0;
- /* check if the KeyingSet is absolute or not (i.e. does it requires sources info) */
- if (ks->flag & KEYINGSET_ABSOLUTE) {
- /* Absolute KeyingSets are simpler to use, as all the destination info has already been
- * provided by the user, and is stored, ready to use, in the KeyingSet paths.
+ /* if relative Keying Sets, poll and build up the paths */
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
+ KeyingSetInfo *ksi = ANIM_keyingset_info_find_named(ks->typeinfo);
+
+ /* clear all existing paths
+ * NOTE: BKE_keyingset_free() frees all of the paths for the KeyingSet, but not the set itself
*/
- for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
- int arraylen, i;
-
- /* get pointer to name of group to add channels to */
- if (ksp->groupmode == KSP_GROUP_NONE)
- groupname= NULL;
- else if (ksp->groupmode == KSP_GROUP_KSNAME)
- groupname= ks->name;
- else
- groupname= ksp->group;
-
- /* init arraylen and i - arraylen should be greater than i so that
- * normal non-array entries get keyframed correctly
- */
- i= ksp->array_index;
- arraylen= i;
-
- /* get length of array if whole array option is enabled */
- if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
-
- RNA_id_pointer_create(ksp->id, &id_ptr);
- if (RNA_path_resolve(&id_ptr, ksp->rna_path, &ptr, &prop) && prop)
- arraylen= RNA_property_array_length(&ptr, prop);
- }
-
- /* we should do at least one step */
- if (arraylen == i)
- arraylen++;
-
- /* for each possible index, perform operation
- * - assume that arraylen is greater than index
+ BKE_keyingset_free(ks);
+
+ /* get the associated 'type info' for this KeyingSet */
+ if (ksi == NULL)
+ return MODIFYKEY_MISSING_TYPEINFO;
+ // TODO: check for missing callbacks!
+
+ /* check if it can be used in the current context */
+ if (ksi->poll(ksi, C)) {
+ /* if a list of data sources are provided, run a special iterator over them,
+ * otherwise, just continue per normal
*/
- for (; i < arraylen; i++) {
- /* action to take depends on mode */
- if (mode == MODIFYKEY_MODE_INSERT)
- success += insert_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag);
- else if (mode == MODIFYKEY_MODE_DELETE)
- success += delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag);
- }
-
- /* set recalc-flags */
- if (ksp->id) {
- switch (GS(ksp->id->name)) {
- case ID_OB: /* Object (or Object-Related) Keyframes */
- {
- Object *ob= (Object *)ksp->id;
-
- ob->recalc |= OB_RECALC;
- }
- break;
- }
+ if (dsources)
+ RKS_ITER_overrides_list(ksi, C, ks, dsources);
+ else
+ ksi->iter(ksi, C, ks);
- /* send notifiers for updates (this doesn't require context to work!) */
- WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
- }
+ /* if we don't have any paths now, then this still qualifies as invalid context */
+ if (ks->paths.first == NULL)
+ return MODIFYKEY_INVALID_CONTEXT;
+ }
+ else {
+ /* poll callback tells us that KeyingSet is useless in current context */
+ return MODIFYKEY_INVALID_CONTEXT;
}
}
- else if (dsources && dsources->first) {
- /* for each one of the 'sources', resolve the template markers and expand arrays, then insert keyframes */
- bCommonKeySrc *cks;
+
+ /* apply the paths as specified in the KeyingSet now */
+ for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
+ int arraylen, i;
+ short kflag2;
- /* for each 'source' for keyframe data, resolve each of the paths from the KeyingSet */
- for (cks= dsources->first; cks; cks= cks->next) {
- /* for each path in KeyingSet, construct a path using the templates */
- for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
- DynStr *pathds= BLI_dynstr_new();
- char *path = NULL;
- int arraylen, i;
-
- /* set initial group name */
- if (cks->id == NULL) {
- printf("ERROR: Skipping 'Common-Key' Source. No valid ID present.\n");
- continue;
- }
- else
- groupname= cks->id->name+2;
-
- /* construct the path */
- // FIXME: this currently only works with a few hardcoded cases
- if ((ksp->templates & KSP_TEMPLATE_PCHAN) && (cks->pchan)) {
- /* add basic pose-channel path access */
- BLI_dynstr_append(pathds, "pose.bones[\"");
- BLI_dynstr_append(pathds, cks->pchan->name);
- BLI_dynstr_append(pathds, "\"]");
-
- /* override default group name */
- groupname= cks->pchan->name;
- }
- if ((ksp->templates & KSP_TEMPLATE_CONSTRAINT) && (cks->con)) {
- /* add basic constraint path access */
- BLI_dynstr_append(pathds, "constraints[\"");
- BLI_dynstr_append(pathds, cks->con->name);
- BLI_dynstr_append(pathds, "\"]");
-
- /* override default group name */
- groupname= cks->con->name;
- }
+ /* since keying settings can be defined on the paths too, extend the path before using it */
+ kflag2 = (kflag | ksp->keyingflag);
+
+ /* get pointer to name of group to add channels to */
+ if (ksp->groupmode == KSP_GROUP_NONE)
+ groupname= NULL;
+ else if (ksp->groupmode == KSP_GROUP_KSNAME)
+ groupname= ks->name;
+ else
+ groupname= ksp->group;
+
+ /* init arraylen and i - arraylen should be greater than i so that
+ * normal non-array entries get keyframed correctly
+ */
+ i= ksp->array_index;
+ arraylen= i;
+
+ /* get length of array if whole array option is enabled */
+ if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+
+ RNA_id_pointer_create(ksp->id, &id_ptr);
+ if (RNA_path_resolve(&id_ptr, ksp->rna_path, &ptr, &prop) && prop)
+ arraylen= RNA_property_array_length(&ptr, prop);
+ }
+
+ /* we should do at least one step */
+ if (arraylen == i)
+ arraylen++;
+
+ /* for each possible index, perform operation
+ * - assume that arraylen is greater than index
+ */
+ for (; i < arraylen; i++) {
+ /* action to take depends on mode */
+ if (mode == MODIFYKEY_MODE_INSERT)
+ success += insert_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2);
+ else if (mode == MODIFYKEY_MODE_DELETE)
+ success += delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2);
+ }
+
+ /* set recalc-flags */
+ if (ksp->id) {
+ switch (GS(ksp->id->name)) {
+ case ID_OB: /* Object (or Object-Related) Keyframes */
{
- /* add property stored in KeyingSet Path */
- if (BLI_dynstr_get_len(pathds))
- BLI_dynstr_append(pathds, ".");
-
- /* apply some further templates? */
- if (ksp->templates & KSP_TEMPLATE_ROT) {
- /* for builtin Keying Sets, this template makes the best fitting path for the
- * current rotation mode of the Object / PoseChannel to be used
- */
- if (strcmp(ksp->rna_path, "rotation")==0) {
- /* get rotation mode */
- short rotmode= (cks->pchan)? (cks->pchan->rotmode) :
- (GS(cks->id->name)==ID_OB)? ( ((Object *)cks->id)->rotmode ) :
- (0);
-
- /* determine path to build */
- if (rotmode == ROT_MODE_QUAT)
- BLI_dynstr_append(pathds, "rotation_quaternion");
- else if (rotmode == ROT_MODE_AXISANGLE)
- BLI_dynstr_append(pathds, "rotation_axis_angle");
- else
- BLI_dynstr_append(pathds, "rotation_euler");
- }
- }
- else {
- /* just directly use the path */
- BLI_dynstr_append(pathds, ksp->rna_path);
- }
-
- /* convert to C-string */
- path= BLI_dynstr_get_cstring(pathds);
- BLI_dynstr_free(pathds);
- }
-
- /* get pointer to name of group to add channels to
- * - KSP_GROUP_TEMPLATE_ITEM is handled above while constructing the paths
- */
- if (ksp->groupmode == KSP_GROUP_NONE)
- groupname= NULL;
- else if (ksp->groupmode == KSP_GROUP_KSNAME)
- groupname= ks->name;
- else if (ksp->groupmode == KSP_GROUP_NAMED)
- groupname= ksp->group;
-
- /* init arraylen and i - arraylen should be greater than i so that
- * normal non-array entries get keyframed correctly
- */
- i= ksp->array_index;
- arraylen= i+1;
-
- /* get length of array if whole array option is enabled */
- if (ksp->flag & KSP_FLAG_WHOLE_ARRAY) {
- PointerRNA id_ptr, ptr;
- PropertyRNA *prop;
+ Object *ob= (Object *)ksp->id;
- RNA_id_pointer_create(cks->id, &id_ptr);
- if (RNA_path_resolve(&id_ptr, path, &ptr, &prop) && prop)
- arraylen= RNA_property_array_length(&ptr, prop);
- }
-
- /* for each possible index, perform operation
- * - assume that arraylen is greater than index
- */
- for (; i < arraylen; i++) {
- /* action to take depends on mode */
- if (mode == MODIFYKEY_MODE_INSERT)
- success+= insert_keyframe(cks->id, act, groupname, path, i, cfra, kflag);
- else if (mode == MODIFYKEY_MODE_DELETE)
- success+= delete_keyframe(cks->id, act, groupname, path, i, cfra, kflag);
+ ob->recalc |= OB_RECALC;
}
-
- /* free the path */
- MEM_freeN(path);
+ break;
}
- /* set recalc-flags */
- if (cks->id) {
- switch (GS(cks->id->name)) {
- case ID_OB: /* Object (or Object-Related) Keyframes */
- {
- Object *ob= (Object *)cks->id;
-
- ob->recalc |= OB_RECALC;
- }
- break;
- }
-
- /* send notifiers for updates (this doesn't require context to work!) */
- WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
- }
+ /* send notifiers for updates (this doesn't require context to work!) */
+ WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
}
}
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
index 4a3ef38daa6..3f26a146c53 100644
--- a/source/blender/editors/armature/editarmature.c
+++ b/source/blender/editors/armature/editarmature.c
@@ -4867,12 +4867,7 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *op)
Object *ob= CTX_data_active_object(C);
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Scaling");
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &ob->id;
+ short autokey = 0;
/* only clear those channels that are not locked */
CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) {
@@ -4885,13 +4880,12 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *op)
/* do auto-keyframing as appropriate */
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
-
/* clear any unkeyed tags */
if (pchan->bone)
pchan->bone->flag &= ~BONE_UNKEYED;
+
+ /* tag for autokeying later */
+ autokey = 1;
}
else {
/* add unkeyed tags */
@@ -4901,6 +4895,16 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ /* perform autokeying on the bones if needed */
+ if (autokey) {
+ /* insert keyframes */
+ ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+
+ /* now recalculate paths */
+ if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
+ ED_pose_recalculate_paths(C, scene, ob);
+ }
+
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
@@ -4930,12 +4934,7 @@ static int pose_clear_loc_exec(bContext *C, wmOperator *op)
Object *ob= CTX_data_active_object(C);
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &ob->id;
+ short autokey = 0;
/* only clear those channels that are not locked */
CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) {
@@ -4949,13 +4948,12 @@ static int pose_clear_loc_exec(bContext *C, wmOperator *op)
/* do auto-keyframing as appropriate */
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
-
/* clear any unkeyed tags */
if (pchan->bone)
pchan->bone->flag &= ~BONE_UNKEYED;
+
+ /* tag for autokeying later */
+ autokey = 1;
}
else {
/* add unkeyed tags */
@@ -4965,6 +4963,16 @@ static int pose_clear_loc_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ /* perform autokeying on the bones if needed */
+ if (autokey) {
+ /* insert keyframes */
+ ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+
+ /* now recalculate paths */
+ if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
+ ED_pose_recalculate_paths(C, scene, ob);
+ }
+
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
@@ -4994,12 +5002,7 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
Object *ob= CTX_data_active_object(C);
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &ob->id;
+ short autokey = 0;
/* only clear those channels that are not locked */
CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) {
@@ -5097,13 +5100,12 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
/* do auto-keyframing as appropriate */
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
-
/* clear any unkeyed tags */
if (pchan->bone)
pchan->bone->flag &= ~BONE_UNKEYED;
+
+ /* tag for autokeying later */
+ autokey = 1;
}
else {
/* add unkeyed tags */
@@ -5113,6 +5115,16 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ /* perform autokeying on the bones if needed */
+ if (autokey) {
+ /* insert keyframes */
+ ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+
+ /* now recalculate paths */
+ if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
+ ED_pose_recalculate_paths(C, scene, ob);
+ }
+
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
/* note, notifier might evolve */
diff --git a/source/blender/editors/armature/poseUtils.c b/source/blender/editors/armature/poseUtils.c
index e2fc2bd4088..ecc84aaf4bb 100644
--- a/source/blender/editors/armature/poseUtils.c
+++ b/source/blender/editors/armature/poseUtils.c
@@ -229,27 +229,28 @@ void poseAnim_mapping_autoKeyframe (bContext *C, Scene *scene, Object *ob, ListB
/* insert keyframes as necessary if autokeyframing */
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
tPChanFCurveLink *pfl;
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &ob->id;
-
/* iterate over each pose-channel affected, applying the changes */
for (pfl= pfLinks->first; pfl; pfl= pfl->next) {
+ ListBase dsources = {NULL, NULL};
bPoseChannel *pchan= pfl->pchan;
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
- /* insert keyframes */
+ /* add datasource override for the PoseChannel so KeyingSet will do right thing */
+ ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
+
+ /* insert keyframes
+ * - these keyingsets here use dsources, since we need to specify exactly which keyframes get affected
+ */
if (pchan->flag & POSE_LOC)
- modify_keyframes(scene, &dsources, NULL, ks_loc, MODIFYKEY_MODE_INSERT, cframe);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks_loc, MODIFYKEY_MODE_INSERT, cframe);
if (pchan->flag & POSE_ROT)
- modify_keyframes(scene, &dsources, NULL, ks_rot, MODIFYKEY_MODE_INSERT, cframe);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks_rot, MODIFYKEY_MODE_INSERT, cframe);
if (pchan->flag & POSE_SIZE)
- modify_keyframes(scene, &dsources, NULL, ks_scale, MODIFYKEY_MODE_INSERT, cframe);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks_scale, MODIFYKEY_MODE_INSERT, cframe);
+
+ /* free the temp info */
+ BLI_freelistN(&dsources);
}
}
}
diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c
index 02194035ee9..8d38d0530ce 100644
--- a/source/blender/editors/armature/poselib.c
+++ b/source/blender/editors/armature/poselib.c
@@ -331,19 +331,14 @@ static int poselib_add_menu_invoke (bContext *C, wmOperator *op, wmEvent *evt)
static int poselib_add_exec (bContext *C, wmOperator *op)
{
- Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_active_object(C);
bAction *act = poselib_validate(ob);
bArmature *arm= (ob) ? ob->data : NULL;
bPose *pose= (ob) ? ob->pose : NULL;
- bPoseChannel *pchan;
TimeMarker *marker;
int frame= RNA_int_get(op->ptr, "frame");
char name[64];
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
/* sanity check (invoke should have checked this anyway) */
if (ELEM3(NULL, ob, arm, pose))
return OPERATOR_CANCELLED;
@@ -373,25 +368,12 @@ static int poselib_add_exec (bContext *C, wmOperator *op)
/* validate name */
BLI_uniquename(&act->markers, marker, "Pose", '.', offsetof(TimeMarker, name), sizeof(marker->name));
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &ob->id;
-
- /* loop through selected posechannels, keying their pose to the action */
- for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
- /* check if available */
- if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
- if (pchan->bone->flag & BONE_SELECTED || pchan->bone==arm->act_bone) {
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
-
- /* KeyingSet to use depends on rotation mode (but that's handled by the templates code) */
- if (poselib_ks_locrotscale == NULL)
- poselib_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
- modify_keyframes(scene, &dsources, act, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)frame);
- }
- }
- }
+ /* KeyingSet to use depends on rotation mode (but that's handled by the templates code) */
+ if (poselib_ks_locrotscale == NULL)
+ poselib_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
+
+ /* make the keyingset use context info to determine where to add keyframes */
+ ANIM_apply_keyingset(C, NULL, act, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)frame);
/* store new 'active' pose number */
act->active_marker= BLI_countlist(&act->markers);
@@ -784,13 +766,6 @@ static void poselib_keytag_pose (bContext *C, Scene *scene, tPoseLib_PreviewData
bAction *act= pld->act;
bActionGroup *agrp;
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &pld->ob->id;
-
/* start tagging/keying */
for (agrp= act->groups.first; agrp; agrp= agrp->next) {
/* only for selected action channels */
@@ -798,21 +773,23 @@ static void poselib_keytag_pose (bContext *C, Scene *scene, tPoseLib_PreviewData
pchan= get_pose_channel(pose, agrp->name);
if (pchan) {
- // TODO: use a standard autokeying function in future (to allow autokeying-editkeys to work)
- if (IS_AUTOKEY_MODE(scene, NORMAL)) {
- /* Set keys on pose
- * - KeyingSet to use depends on rotation mode
- * (but that's handled by the templates code)
- */
+ if (autokeyframe_cfra_can_key(scene, &pld->ob->id)) {
+ ListBase dsources = {NULL, NULL};
+
+ /* get KeyingSet to use */
// TODO: for getting the KeyingSet used, we should really check which channels were affected
+ // TODO: this should get modified so that custom props are taken into account too!
if (poselib_ks_locrotscale == NULL)
poselib_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
-
- /* now insert the keyframe */
- modify_keyframes(scene, &dsources, NULL, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ /* now insert the keyframe(s) using the Keying Set
+ * 1) add datasource override for the PoseChannel
+ * 2) insert keyframes
+ * 3) free the extra info
+ */
+ ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan);
+ ANIM_apply_keyingset(C, &dsources, NULL, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
/* clear any unkeyed tags */
if (pchan->bone)
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index a162c8eb21a..f20c79da17e 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -849,14 +849,14 @@ void free_posebuf(void)
{
if (g_posebuf) {
bPoseChannel *pchan;
-
+
for (pchan= g_posebuf->chanbase.first; pchan; pchan= pchan->next) {
if(pchan->prop) {
IDP_FreeProperty(pchan->prop);
MEM_freeN(pchan->prop);
}
}
-
+
/* was copied without constraints */
BLI_freelistN(&g_posebuf->chanbase);
MEM_freeN(g_posebuf);
@@ -908,9 +908,6 @@ void POSE_OT_copy (wmOperatorType *ot)
/* Pointers to the builtin KeyingSets that we want to use */
static KeyingSet *posePaste_ks_locrotscale = NULL; /* the only keyingset we'll need */
-/* transform.h */
-extern void autokeyframe_pose_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode, short targetless_ik);
-
static int pose_paste_exec (bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
@@ -919,13 +916,6 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
char name[32];
int flip= RNA_boolean_get(op->ptr, "flipped");
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &ob->id;
-
/* sanity checks */
if ELEM(NULL, ob, ob->pose)
return OPERATOR_CANCELLED;
@@ -974,14 +964,14 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
/* quat/euler to axis angle */
if (chan->rotmode > 0)
- eulO_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,chan->eul, chan->rotmode);
+ eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
else
- quat_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,chan->quat);
+ quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
}
else {
/* euler/axis-angle to quat */
if (chan->rotmode > 0)
- eulO_to_quat( pchan->quat,chan->eul, chan->rotmode);
+ eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
else
axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
}
@@ -998,10 +988,10 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
float eul[3];
- axis_angle_to_eulO( eul, EULER_ORDER_DEFAULT,pchan->rotAxis, pchan->rotAngle);
+ axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
eul[1]*= -1;
eul[2]*= -1;
- eulO_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,eul, EULER_ORDER_DEFAULT);
+ eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
// experimental method (uncomment to test):
#if 0
@@ -1013,62 +1003,55 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
else {
float eul[3];
- quat_to_eul( eul,pchan->quat);
+ quat_to_eul(eul, pchan->quat);
eul[1]*= -1;
eul[2]*= -1;
- eul_to_quat( pchan->quat,eul);
+ eul_to_quat(pchan->quat, eul);
}
}
/* ID property */
- if(pchan->prop) {
+ if (pchan->prop) {
IDP_FreeProperty(pchan->prop);
MEM_freeN(pchan->prop);
pchan->prop= NULL;
}
-
- if(chan->prop) {
+
+ if (chan->prop)
pchan->prop= IDP_CopyProperty(chan->prop);
+
+ /* keyframing tagging */
+ if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+ ListBase dsources = {NULL, NULL};
+
+ /* get KeyingSet to use */
+ // TODO: for getting the KeyingSet used, we should really check which channels were affected
+ // TODO: this should get modified so that custom props are taken into account too!
+ if (posePaste_ks_locrotscale == NULL)
+ posePaste_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
+
+ /* now insert the keyframe(s) using the Keying Set
+ * 1) add datasource override for the PoseChannel
+ * 2) insert keyframes
+ * 3) free the extra info
+ */
+ ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
+ ANIM_apply_keyingset(C, &dsources, NULL, posePaste_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
+
+ /* clear any unkeyed tags */
+ if (chan->bone)
+ chan->bone->flag &= ~BONE_UNKEYED;
}
-
- /* auto key, TODO, fix up this INSERTAVAIL vs all other cases */
- if (IS_AUTOKEY_FLAG(INSERTAVAIL) == 0) { /* deal with this case later */
- if (autokeyframe_cfra_can_key(scene, &ob->id)) {
-
- /* Set keys on pose
- * - KeyingSet to use depends on rotation mode
- * (but that's handled by the templates code)
- */
- // TODO: for getting the KeyingSet used, we should really check which channels were affected
- if (posePaste_ks_locrotscale == NULL)
- posePaste_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
-
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
-
- modify_keyframes(scene, &dsources, NULL, posePaste_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA);
-
- /* clear any unkeyed tags */
- if (chan->bone)
- chan->bone->flag &= ~BONE_UNKEYED;
- }
- else {
- /* add unkeyed tags */
- if (chan->bone)
- chan->bone->flag |= BONE_UNKEYED;
- }
+ else {
+ /* add unkeyed tags */
+ if (chan->bone)
+ chan->bone->flag |= BONE_UNKEYED;
}
}
}
}
-
- if (IS_AUTOKEY_FLAG(INSERTAVAIL)) {
- View3D *v3d= CTX_wm_view3d(C);
- autokeyframe_pose_cb_func(C, scene, v3d, ob, TFM_TRANSLATION, 0);
- autokeyframe_pose_cb_func(C, scene, v3d, ob, TFM_ROTATION, 0);
- autokeyframe_pose_cb_func(C, scene, v3d, ob, TFM_TIME_SCALE, 0);
- }
-
+
/* Update event for pose and deformation children */
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
@@ -1077,13 +1060,13 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
}
else {
/* need to trick depgraph, action is not allowed to execute on pose */
+ // XXX: this is probably not an issue anymore
where_is_pose(scene, ob);
ob->recalc= 0;
}
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
- WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); // XXX not really needed, but here for completeness...
return OPERATOR_FINISHED;
}
@@ -1754,13 +1737,7 @@ static int pose_flip_quats_exec (bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_active_object(C);
-
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &ob->id;
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
/* loop through all selected pchans, flipping and keying (as needed) */
CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
@@ -1773,20 +1750,18 @@ static int pose_flip_quats_exec (bContext *C, wmOperator *op)
pchan->quat[2]= -pchan->quat[2];
pchan->quat[3]= -pchan->quat[3];
- /* perform auto-keying
- * NOTE: paths don't need recalculation here, since the orientations shouldn't have changed
- */
+ /* tagging */
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- /* Set keys on pose
- * - KeyingSet to use depends on rotation mode
- * (but that's handled by the templates code)
- */
- KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
+ ListBase dsources = {NULL, NULL};
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
-
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ /* now insert the keyframe(s) using the Keying Set
+ * 1) add datasource override for the PoseChannel
+ * 2) insert keyframes
+ * 3) free the extra info
+ */
+ ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
/* clear any unkeyed tags */
if (pchan->bone)
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 2c58d9e3ff5..576069d78e8 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -89,8 +89,6 @@ int insert_vert_fcurve(struct FCurve *fcu, float x, float y, short flag);
*/
short insert_keyframe_direct(struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, float cfra, short flag);
-
-
/* -------- */
/* Main Keyframing API calls:
@@ -106,48 +104,92 @@ short delete_keyframe(struct ID *id, struct bAction *act, const char group[], co
/* ************ Keying Sets ********************** */
-/* temporary struct to gather data combos to keyframe
- * (is used by modify_keyframes for 'relative' KeyingSets, provided via the dsources arg)
- */
-typedef struct bCommonKeySrc {
- struct bCommonKeySrc *next, *prev;
-
- /* general data/destination-source settings */
- struct ID *id; /* id-block this comes from */
+/* forward decl. for this struct which is declared a bit later... */
+struct KeyingSetInfo;
+
+/* Polling Callback for KeyingSets */
+typedef int (*cbKeyingSet_Poll)(struct KeyingSetInfo *ksi, struct bContext *C);
+/* Context Iterator Callback for KeyingSets */
+typedef void (*cbKeyingSet_Iterator)(struct KeyingSetInfo *ksi, struct bContext *C, struct KeyingSet *ks);
+/* Property Specifier Callback for KeyingSets (called from iterators) */
+typedef void (*cbKeyingSet_Generate)(struct KeyingSetInfo *ksi, struct bContext *C, struct KeyingSet *ks, struct PointerRNA *ptr);
+
+
+/* Callback info for 'Procedural' KeyingSets to use */
+typedef struct KeyingSetInfo {
+ struct KeyingSetInfo *next, *prev;
+
+ /* info */
+ /* identifier so that user can hook this up to a KeyingSet */
+ char name[64];
+ /* keying settings */
+ short keyingflag;
+ /* builtin? */
+ short builtin;
+
+ /* polling callbacks */
+ /* callback for polling the context for whether the right data is available */
+ cbKeyingSet_Poll poll;
- /* specific cases */
- struct bPoseChannel *pchan;
- struct bConstraint *con;
-} bCommonKeySrc;
+ /* generate callbacks */
+ /* iterator to use to go through collections of data in context
+ * - this callback is separate from the 'adding' stage, allowing
+ * BuiltIn KeyingSets to be manually specified to use
+ */
+ cbKeyingSet_Iterator iter;
+ /* generator to use to add properties based on the data found by iterator */
+ cbKeyingSet_Generate generate;
+
+ /* RNA integration */
+ ExtensionRNA ext;
+} KeyingSetInfo;
/* -------- */
+/* Add another data source for Relative Keying Sets to be evaluated with */
+void ANIM_relative_keyingset_add_source(ListBase *dsources, struct ID *id, struct StructRNA *srna, void *data);
+
+
/* mode for modify_keyframes */
typedef enum eModifyKey_Modes {
MODIFYKEY_MODE_INSERT = 0,
MODIFYKEY_MODE_DELETE,
} eModifyKey_Modes;
-/* Keyframing Helper Call - use the provided Keying Set to Add/Remove Keyframes */
-int modify_keyframes(struct Scene *scene, struct ListBase *dsources, struct bAction *act, struct KeyingSet *ks, short mode, float cfra);
+/* return codes for errors (with Relative KeyingSets) */
+typedef enum eModifyKey_Returns {
+ /* context info was invalid for using the Keying Set */
+ MODIFYKEY_INVALID_CONTEXT = -1,
+ /* there isn't any typeinfo for generating paths from context */
+ MODIFYKEY_MISSING_TYPEINFO = -2,
+} eModifyKey_Returns;
-/* -------- */
+/* use the specified KeyingSet to add/remove various Keyframes on the specified frame */
+int ANIM_apply_keyingset(struct bContext *C, ListBase *dsources, struct bAction *act, struct KeyingSet *ks, short mode, float cfra);
-/* Generate menu of KeyingSets */
-char *ANIM_build_keyingsets_menu(struct ListBase *list, short for_edit);
+/* -------- */
/* Get the first builtin KeyingSet with the given name, which occurs after the given one (or start of list if none given) */
-struct KeyingSet *ANIM_builtin_keyingset_get_named(struct KeyingSet *prevKS, char name[]);
+struct KeyingSet *ANIM_builtin_keyingset_get_named(struct KeyingSet *prevKS, const char name[]);
+
+/* Find KeyingSet type info given a name */
+KeyingSetInfo *ANIM_keyingset_info_find_named(const char name[]);
-/* Initialise builtin KeyingSets on startup */
-void init_builtin_keyingsets(void);
+/* for RNA type registrations... */
+void ANIM_keyingset_info_register(const struct bContext *C, KeyingSetInfo *ksi);
+void ANIM_keyingset_info_unregister(const struct bContext *C, KeyingSetInfo *ksi);
+/* cleanup on exit */
+void ANIM_keyingset_infos_exit(void);
/* -------- */
/* Get the active KeyingSet for the given scene */
struct KeyingSet *ANIM_scene_get_active_keyingset(struct Scene *scene);
+/* Check if KeyingSet can be used in the current context */
+short ANIM_keyingset_context_ok_poll(struct bContext *C, struct KeyingSet *ks);
+
/* ************ Drivers ********************** */
/* Returns whether there is a driver in the copy/paste buffer to paste */
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 30df347bc60..db15322bbc4 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -75,32 +75,35 @@
static int object_location_clear_exec(bContext *C, wmOperator *op)
{
- Scene *scene= CTX_data_scene(C);
-
+ Scene *scene = CTX_data_scene(C);
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
/* clear location of selected objects if not in weight-paint mode */
CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
- if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
- if((ob->protectflag & OB_LOCK_LOCX)==0)
+ if (!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
+ /* clear location if not locked */
+ if ((ob->protectflag & OB_LOCK_LOCX)==0)
ob->loc[0]= ob->dloc[0]= 0.0f;
- if((ob->protectflag & OB_LOCK_LOCY)==0)
+ if ((ob->protectflag & OB_LOCK_LOCY)==0)
ob->loc[1]= ob->dloc[1]= 0.0f;
- if((ob->protectflag & OB_LOCK_LOCZ)==0)
+ if ((ob->protectflag & OB_LOCK_LOCZ)==0)
ob->loc[2]= ob->dloc[2]= 0.0f;
- /* do auto-keyframing as appropriate */
+ /* auto keyframing */
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- /* init cks for this object, then use the relative KeyingSets to keyframe it */
- cks.id= &ob->id;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ ListBase dsources = {NULL, NULL};
+
+ /* now insert the keyframe(s) using the Keying Set
+ * 1) add datasource override for the PoseChannel
+ * 2) insert keyframes
+ * 3) free the extra info
+ */
+ ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
}
}
+
ob->recalc |= OB_RECALC_OB;
}
CTX_DATA_END;
@@ -131,17 +134,12 @@ void OBJECT_OT_location_clear(wmOperatorType *ot)
static int object_rotation_clear_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
-
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
/* clear rotation of selected objects if not in weight-paint mode */
CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
+ /* clear rotations that aren't locked */
if (ob->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) {
if (ob->protectflag & OB_LOCK_ROT4D) {
/* perform clamping on a component by component basis */
@@ -233,13 +231,21 @@ static int object_rotation_clear_exec(bContext *C, wmOperator *op)
}
}
- /* do auto-keyframing as appropriate */
+ /* auto keyframing */
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- /* init cks for this object, then use the relative KeyingSets to keyframe it */
- cks.id= &ob->id;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ ListBase dsources = {NULL, NULL};
+
+ /* now insert the keyframe(s) using the Keying Set
+ * 1) add datasource override for the PoseChannel
+ * 2) insert keyframes
+ * 3) free the extra info
+ */
+ ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
}
}
+
ob->recalc |= OB_RECALC_OB;
}
CTX_DATA_END;
@@ -270,35 +276,37 @@ void OBJECT_OT_rotation_clear(wmOperatorType *ot)
static int object_scale_clear_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
-
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Scaling");
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
-
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
/* clear scales of selected objects if not in weight-paint mode */
CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
- if((ob->protectflag & OB_LOCK_SCALEX)==0) {
+ /* clear scale factors which are not locked */
+ if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
ob->dsize[0]= 0.0f;
ob->size[0]= 1.0f;
}
- if((ob->protectflag & OB_LOCK_SCALEY)==0) {
+ if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
ob->dsize[1]= 0.0f;
ob->size[1]= 1.0f;
}
- if((ob->protectflag & OB_LOCK_SCALEZ)==0) {
+ if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
ob->dsize[2]= 0.0f;
ob->size[2]= 1.0f;
}
- /* do auto-keyframing as appropriate */
+ /* auto keyframing */
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- /* init cks for this object, then use the relative KeyingSets to keyframe it */
- cks.id= &ob->id;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ ListBase dsources = {NULL, NULL};
+
+ /* now insert the keyframe(s) using the Keying Set
+ * 1) add datasource override for the PoseChannel
+ * 2) insert keyframes
+ * 3) free the extra info
+ */
+ ANIM_relative_keyingset_add_source(&dsources, &ob->id, NULL, NULL);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+ BLI_freelistN(&dsources);
}
}
ob->recalc |= OB_RECALC_OB;
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 38a7163d35f..828d5368834 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -2323,7 +2323,7 @@ static void flyEvent(FlyInfo *fly, wmEvent *event)
}
}
-static int flyApply(FlyInfo *fly)
+static int flyApply(bContext *C, FlyInfo *fly)
{
/*
fly mode - Shift+F
@@ -2606,13 +2606,10 @@ static int flyApply(FlyInfo *fly)
/* record the motion */
if (autokeyframe_cfra_can_key(scene, id_key)) {
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
- int cfra = CFRA;
+ ListBase dsources = {NULL, NULL};
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= id_key;
+ /* add datasource override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
/* insert keyframes
* 1) on the first frame
@@ -2621,12 +2618,15 @@ static int flyApply(FlyInfo *fly)
*/
if (fly->xlock || fly->zlock || moffset[0] || moffset[1]) {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
}
if (fly->speed) {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
}
+
+ /* free temp data */
+ BLI_freelistN(&dsources);
}
}
} else
@@ -2689,7 +2689,7 @@ static int fly_modal(bContext *C, wmOperator *op, wmEvent *event)
flyEvent(fly, event);
if(event->type==TIMER && event->customdata == fly->timer)
- flyApply(fly);
+ flyApply(C, fly);
if(fly->redraw) {
ED_region_tag_redraw(CTX_wm_region(C));
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 372aa42bac3..9c570e10406 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -102,20 +102,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
-//#include "BIF_editview.h"
-//#include "BIF_editlattice.h"
-//#include "BIF_editconstraint.h"
-//#include "BIF_editmesh.h"
-//#include "BIF_editsima.h"
-//#include "BIF_editparticle.h"
#include "BIF_gl.h"
-//#include "BIF_poseobject.h"
-//#include "BIF_meshtools.h"
-//#include "BIF_mywindow.h"
-//#include "BIF_resources.h"
-//#include "BIF_screen.h"
-//#include "BIF_space.h"
-//#include "BIF_toolbox.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -132,19 +119,11 @@
#include "UI_view2d.h"
-//#include "BSE_edit.h"
-//#include "BDR_editobject.h" // reset_slowparents()
-//#include "BDR_gpencil.h"
-
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
-//#include "editmesh.h"
-//
-//#include "blendef.h"
-//
-//#include "mydevice.h"
+#include "RNA_access.h"
extern ListBase editelems;
@@ -4484,20 +4463,21 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
// TODO: this should probably be done per channel instead...
if (autokeyframe_cfra_can_key(scene, id)) {
KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
+ ListBase dsources = {NULL, NULL};
float cfra= (float)CFRA; // xxx this will do for now
short flag = 0;
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &ob->id;
-
+ /* get flags used for inserting keyframes */
flag = ANIM_get_keyframing_flags(scene, 1);
+ /* add datasource override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL);
+
if (IS_AUTOKEY_FLAG(ONLYKEYINGSET) && (active_ks)) {
- /* only insert into active keyingset */
- modify_keyframes(scene, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
+ /* only insert into active keyingset
+ * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden spe
+ */
+ ANIM_apply_keyingset(C, NULL, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
}
else if (IS_AUTOKEY_FLAG(INSERTAVAIL)) {
AnimData *adt= ob->adt;
@@ -4543,22 +4523,25 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
/* insert keyframes for the affected sets of channels using the builtin KeyingSets found */
if (doLoc) {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
if (doRot) {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
if (doScale) {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Scale");
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
}
/* insert keyframe in all (transform) channels */
else {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
+
+ /* free temp info */
+ BLI_freelistN(&dsources);
}
}
@@ -4579,15 +4562,9 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
// TODO: this should probably be done per channel instead...
if (autokeyframe_cfra_can_key(scene, id)) {
KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
- bCommonKeySrc cks;
- ListBase dsources = {&cks, &cks};
float cfra= (float)CFRA;
short flag= 0;
- /* init common-key-source for use by KeyingSets */
- memset(&cks, 0, sizeof(bCommonKeySrc));
- cks.id= &ob->id;
-
/* flag is initialised from UserPref keyframing settings
* - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get
* visual keyframes even if flag not set, as it's not that useful otherwise
@@ -4600,14 +4577,18 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
if (pchan->bone->flag & BONE_TRANSFORM) {
+ ListBase dsources = {NULL, NULL};
+
/* clear any 'unkeyed' flag it may have */
pchan->bone->flag &= ~BONE_UNKEYED;
+ /* add datasource override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan);
+
/* only insert into active keyingset? */
+ // TODO: move this first case out of the loop
if (IS_AUTOKEY_FLAG(ONLYKEYINGSET) && (active_ks)) {
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
- modify_keyframes(scene, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, NULL, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
}
/* only insert into available channels? */
else if (IS_AUTOKEY_FLAG(INSERTAVAIL)) {
@@ -4656,34 +4637,25 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
if (doLoc) {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location");
-
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
if (doRot) {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
-
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
if (doScale) {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Scale");
-
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
}
/* insert keyframe in all (transform) channels */
else {
KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
-
- /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
- cks.pchan= pchan;
- modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
}
+
+ /* free temp info */
+ BLI_freelistN(&dsources);
}
}