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:
-rw-r--r--source/blender/blenkernel/BKE_animsys.h16
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c112
-rw-r--r--source/blender/blenkernel/intern/blender.c1
-rw-r--r--source/blender/blenkernel/intern/scene.c1
-rw-r--r--source/blender/blenloader/intern/readfile.c52
-rw-r--r--source/blender/blenloader/intern/writefile.c25
-rw-r--r--source/blender/editors/animation/keyframing.c264
-rw-r--r--source/blender/editors/include/ED_keyframing.h5
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_graph/graph_draw.c3
-rw-r--r--source/blender/editors/space_outliner/outliner.c40
-rw-r--r--source/blender/editors/space_outliner/outliner_header.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h2
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c7
-rw-r--r--source/blender/editors/space_time/time_header.c17
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c1
-rw-r--r--source/blender/makesdna/DNA_anim_types.h71
-rw-r--r--source/blender/makesdna/DNA_scene_types.h7
18 files changed, 524 insertions, 103 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 3b6b01a2341..47eaf68cc83 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -9,6 +9,7 @@ struct ID;
struct ListBase;
struct Main;
struct AnimData;
+struct KeyingSet;
/* ************************************* */
/* AnimData API */
@@ -26,6 +27,21 @@ void BKE_free_animdata(struct ID *id);
struct AnimData *BKE_copy_animdata(struct AnimData *adt);
/* ************************************* */
+/* KeyingSets API */
+
+/* Used to create a new 'custom' KeyingSet for the user, that will be automatically added to the stack */
+struct KeyingSet *BKE_keyingset_add(struct ListBase *list, const char name[], short flag, short keyingflag);
+
+/* Add a destination to a KeyingSet */
+void BKE_keyingset_add_destination(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, int flag);
+
+/* Free data for KeyingSet but not set itself */
+void BKE_keyingset_free(struct KeyingSet *ks);
+
+/* Free all the KeyingSets in the given list */
+void BKE_keyingsets_free(struct ListBase *list);
+
+/* ************************************* */
// TODO: overrides, remapping, and path-finding api's
/* ************************************* */
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index a7e65a9c585..55597b635c9 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -158,6 +158,118 @@ AnimData *BKE_copy_animdata (AnimData *adt)
return dadt;
}
+/* *********************************** */
+/* KeyingSet API */
+
+/* NOTES:
+ * It is very likely that there will be two copies of the api - one for internal use,
+ * and one 'operator' based wrapper of the internal API, which should allow for access
+ * from Python/scripts so that riggers can automate the creation of KeyingSets for their rigs.
+ */
+
+/* Defining Tools --------------------------- */
+
+/* Used to create a new 'custom' KeyingSet for the user, that will be automatically added to the stack */
+KeyingSet *BKE_keyingset_add (ListBase *list, const char name[], short flag, short keyingflag)
+{
+ KeyingSet *ks;
+
+ /* allocate new KeyingSet */
+ ks= MEM_callocN(sizeof(KeyingSet), "KeyingSet");
+
+ BLI_snprintf(ks->name, 64, name);
+
+ ks->flag= flag;
+ ks->keyingflag= keyingflag;
+
+ /* add KeyingSet to list */
+ BLI_addtail(list, ks);
+
+ /* return new KeyingSet for further editing */
+ return ks;
+}
+
+/* Add a destination to a KeyingSet. Nothing is returned for now...
+ * Checks are performed to ensure that destination is appropriate for the KeyingSet in question
+ */
+void BKE_keyingset_add_destination (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int flag)
+{
+ KS_Path *ksp;
+
+ /* sanity checks */
+ if ELEM(NULL, ks, rna_path)
+ return;
+
+ /* ID is optional, and should only be provided for absolute KeyingSets */
+ if (id) {
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0)
+ return;
+ }
+
+ /* allocate a new KeyingSet Path */
+ ksp= MEM_callocN(sizeof(KS_Path), "KeyingSet Path");
+
+ /* just store absolute info */
+ if (ks->flag & KEYINGSET_ABSOLUTE) {
+ ksp->id= id;
+ BLI_snprintf(ksp->group, 64, group_name);
+ }
+
+ /* just copy path info */
+ // XXX no checks are performed for templates yet
+ // should array index be checked too?
+ ksp->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
+ ksp->array_index= array_index;
+
+ /* store flags */
+ ksp->flag= flag;
+
+ /* add KeyingSet path to KeyingSet */
+ BLI_addtail(&ks->paths, ksp);
+}
+
+
+/* Freeing Tools --------------------------- */
+
+/* Free data for KeyingSet but not set itself */
+void BKE_keyingset_free (KeyingSet *ks)
+{
+ KS_Path *ksp, *kspn;
+
+ /* sanity check */
+ if (ks == NULL)
+ return;
+
+ /* free each path as we go to avoid looping twice */
+ for (ksp= ks->paths.first; ksp; ksp= kspn) {
+ kspn= ksp->next;
+
+ /* free RNA-path info */
+ MEM_freeN(ksp->rna_path);
+
+ /* free path itself */
+ BLI_freelinkN(&ks->paths, ks);
+ }
+}
+
+/* Free all the KeyingSets in the given list */
+void BKE_keyingsets_free (ListBase *list)
+{
+ KeyingSet *ks, *ksn;
+
+ /* sanity check */
+ if (list == NULL)
+ return;
+
+ /* loop over KeyingSets freeing them
+ * - BKE_keyingset_free() doesn't free the set itself, but it frees its sub-data
+ */
+ for (ks= list->first; ks; ks= ksn) {
+ ksn= ks->next;
+ BKE_keyingset_free(ks);
+ BLI_freelinkN(list, ks);
+ }
+}
/* ***************************************** */
/* Evaluation Data-Setting Backend */
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 94a460ee0a0..4ad7d6da608 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -65,6 +65,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_blender.h"
#include "BKE_context.h"
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 7b3ac9e4ec2..7db96c07592 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -150,6 +150,7 @@ void free_scene(Scene *sce)
#endif
BKE_free_animdata((ID *)sce);
+ BKE_keyingsets_free(&sce->keyingsets);
if (sce->r.avicodecdata) {
free_avicodecdata(sce->r.avicodecdata);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 2a0f98cfe8d..b3eee6e552e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1929,6 +1929,39 @@ static void direct_link_action(FileData *fd, bAction *act)
/* ------- */
+static void lib_link_keyingsets(FileData *fd, ID *id, ListBase *list)
+{
+ KeyingSet *ks;
+ KS_Path *ksp;
+
+ /* here, we're only interested in the ID pointer stored in some of the paths */
+ for (ks= list->first; ks; ks= ks->next) {
+ for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
+ ksp->id= newlibadr(fd, id->lib, ksp->id);
+ }
+ }
+}
+
+/* NOTE: this assumes that link_list has already been called on the list */
+static void direct_link_keyingsets(FileData *fd, ListBase *list)
+{
+ KeyingSet *ks;
+ KS_Path *ksp;
+
+ /* link KeyingSet data to KeyingSet again (non ID-libs) */
+ for (ks= list->first; ks; ks= ks->next) {
+ /* paths */
+ link_list(fd, &ks->paths);
+
+ for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
+ /* rna path */
+ ksp->rna_path= newdataadr(fd, ksp->rna_path);
+ }
+ }
+}
+
+/* ------- */
+
static void lib_link_animdata(FileData *fd, ID *id, AnimData *adt)
{
if (adt == NULL)
@@ -3698,6 +3731,8 @@ static void lib_link_scene(FileData *fd, Main *main)
if (sce->id.properties) IDP_LibLinkProperty(sce->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
if (sce->adt) lib_link_animdata(fd, &sce->id, sce->adt);
+ lib_link_keyingsets(fd, &sce->id, &sce->keyingsets);
+
sce->camera= newlibadr(fd, sce->id.lib, sce->camera);
sce->world= newlibadr_us(fd, sce->id.lib, sce->world);
sce->set= newlibadr(fd, sce->id.lib, sce->set);
@@ -3791,6 +3826,9 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->adt= newdataadr(fd, sce->adt);
direct_link_animdata(fd, sce->adt);
+ link_list(fd, &sce->keyingsets);
+ direct_link_keyingsets(fd, &sce->keyingsets);
+
sce->basact= newdataadr(fd, sce->basact);
sce->radio= newdataadr(fd, sce->radio);
@@ -9124,6 +9162,19 @@ static void expand_action(FileData *fd, Main *mainvar, bAction *act)
}
}
+static void expand_keyingsets(FileData *fd, Main *mainvar, ListBase *list)
+{
+ KeyingSet *ks;
+ KS_Path *ksp;
+
+ /* expand the ID-pointers in KeyingSets's paths */
+ for (ks= list->first; ks; ks= ks->next) {
+ for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
+ expand_doit(fd, mainvar, ksp->id);
+ }
+ }
+}
+
static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
{
FCurve *fcd;
@@ -9655,6 +9706,7 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
if(sce->adt)
expand_animdata(fd, mainvar, sce->adt);
+ expand_keyingsets(fd, mainvar, &sce->keyingsets);
if(sce->nodetree)
expand_nodetree(fd, mainvar, sce->nodetree);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 9c94842ac08..623d1eebe31 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -855,6 +855,26 @@ static void write_actions(WriteData *wd, ListBase *idbase)
mywrite(wd, MYWRITE_FLUSH, 0);
}
+static void write_keyingsets(WriteData *wd, ListBase *list)
+{
+ KeyingSet *ks;
+ KS_Path *ksp;
+
+ for (ks= list->first; ks; ks= ks->next) {
+ /* KeyingSet */
+ writestruct(wd, DATA, "KeyingSet", 1, ks);
+
+ /* Paths */
+ for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
+ /* Path */
+ writestruct(wd, DATA, "KS_Path", 1, ksp);
+
+ if (ksp->rna_path)
+ writedata(wd, DATA, strlen(ksp->rna_path)+1, ksp->rna_path);
+ }
+ }
+}
+
static void write_animdata(WriteData *wd, AnimData *adt)
{
AnimOverride *aor;
@@ -1533,6 +1553,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
if (sce->id.properties) IDP_WriteProperty(sce->id.properties, wd);
if (sce->adt) write_animdata(wd, sce->adt);
+ write_keyingsets(wd, &sce->keyingsets);
/* direct data */
base= sce->base.first;
@@ -1616,9 +1637,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
writestruct(wd, DATA, "MetaStack", 1, ms);
}
}
-
+
write_scriptlink(wd, &sce->scriptlink);
-
+
if (sce->r.avicodecdata) {
writestruct(wd, DATA, "AviCodecData", 1, sce->r.avicodecdata);
if (sce->r.avicodecdata->lpFormat) writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index df3a7b85a45..42ed4fddc99 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -30,6 +30,7 @@
#include "BKE_fcurve.h"
#include "BKE_utildefines.h"
#include "BKE_context.h"
+#include "BKE_report.h"
#include "BKE_key.h"
#include "BKE_material.h"
@@ -39,6 +40,8 @@
#include "ED_screen.h"
#include "ED_util.h"
+#include "UI_interface.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -63,35 +66,6 @@ typedef struct bCommonKeySrc {
bPoseChannel *pchan; /* only needed when doing recalcs... */
} bCommonKeySrc;
-/* -------------- Keying Sets ------------------- */
-
-#if 0 // XXX I'm not sure how these will work for now...
-
-/* keying set - a set of channels that will be keyframed together */
-// TODO: move this to a header to allow custom sets someday?
-typedef struct bKeyingSet {
- /* callback func to consider if keyingset should be included
- * (by default, if this is undefined, item will be shown)
- */
- short (*include_cb)(struct bKeyingSet *, const char *);
-
- char name[48]; /* name of keyingset */
- int blocktype; /* nearest ID-blocktype to where data can be found */
- short flag; /* flags to use when setting keyframes */
-
- short chan_num; /* number of channels to insert keyframe in */
- char (*paths)[256]; /* adrcodes for channels to insert keys for (ideally would be variable-len, but limit of 32 will suffice) */
-} bKeyingSet;
-
-/* keying set context - an array of keying sets and the number of them */
-typedef struct bKeyingContext {
- bKeyingSet *keyingsets; /* array containing the keyingsets of interest */
- bKeyingSet *lastused; /* item that was chosen last time*/
- int tot; /* number of keyingsets in */
-} bKeyingContext;
-
-#endif
-
/* ******************************************* */
/* Animation Data Validation */
@@ -184,7 +158,7 @@ FCurve *verify_fcurve (ID *id, const char group[], const char rna_path[], const
/* -------------- BezTriple Insertion -------------------- */
/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */
-#define BEZT_INSERT_THRESH 0.00001
+#define BEZT_INSERT_THRESH 0.00001f
/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu)
* Returns the index to insert at (data already at that index will be offset if replace is 0)
@@ -899,6 +873,37 @@ enum {
COMMONKEY_MODE_DELETE,
} eCommonModifyKey_Modes;
+
+/* 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)
+{
+ DynStr *pupds= BLI_dynstr_new();
+ KeyingSet *ks;
+ char buf[64];
+ char *str;
+
+ /* add title first */
+ BLI_dynstr_append(pupds, "Keying Sets%t|");
+
+ /* add dummy entry for none-active */
+ BLI_dynstr_append(pupds, "<No Keying Set Active>%x0|");
+
+ /* loop through keyingsets, adding them */
+ for (ks= list->first; ks; ks= ks->next) {
+ BLI_dynstr_append(pupds, ks->name);
+ BLI_snprintf( buf, 64, "%s", ((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;
+}
+
#if 0 // XXX old keyingsets code based on adrcodes... to be restored in due course
/* --------- KeyingSet Adrcode Getters ------------ */
@@ -1786,57 +1791,6 @@ static void commonkey_context_refresh (bContext *C)
/* --- */
-/* Build menu-string of available keying-sets (allocates memory for string)
- * NOTE: mode must not be longer than 64 chars
- */
-static char *build_keyingsets_menu (bKeyingContext *ksc, const char mode[48])
-{
- DynStr *pupds= BLI_dynstr_new();
- bKeyingSet *ks;
- char buf[64];
- char *str;
- int i, n;
-
- /* add title first */
- BLI_snprintf(buf, 64, "%s Key %%t|", mode);
- BLI_dynstr_append(pupds, buf);
-
- /* loop through keyingsets, adding them */
- for (ks=ksc->keyingsets, i=0, n=1; i < ksc->tot; ks++, i++, n++) {
- /* check if keyingset can be used */
- if (ks->flag == -1) {
- /* optional separator? */
- if (ks->include_cb) {
- if (ks->include_cb(ks, mode)) {
- BLI_snprintf( buf, 64, "%s%s", ks->name, ((n < ksc->tot)?"|":"") );
- BLI_dynstr_append(pupds, buf);
- }
- }
- else {
- BLI_snprintf( buf, 64, "%%l%s", ((n < ksc->tot)?"|":"") );
- BLI_dynstr_append(pupds, buf);
- }
- }
- else if ( (ks->include_cb==NULL) || (ks->include_cb(ks, mode)) ) {
- /* entry can be included */
- BLI_dynstr_append(pupds, ks->name);
-
- /* check if special "shapekey" entry */
- if (ks->flag == -3)
- BLI_snprintf( buf, 64, "%%x0%s", ((n < ksc->tot)?"|":"") );
- else
- BLI_snprintf( buf, 64, "%%x%d%s", n, ((n < ksc->tot)?"|":"") );
- BLI_dynstr_append(pupds, buf);
- }
- }
-
- /* convert to normal MEM_malloc'd string */
- str= BLI_dynstr_get_cstring(pupds);
- BLI_dynstr_free(pupds);
-
- return str;
-}
-
/* Get the keying set that was chosen by the user from the menu */
static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index)
{
@@ -2033,6 +1987,68 @@ void common_modifykey (bContext *C, short mode)
#endif // XXX old keyingsets code based on adrcodes... to be restored in due course
+/* Given a KeyingSet and context info (if required), modify keyframes for the channels specified
+ * 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
+ */
+static int commonkey_modifykey (ListBase *dsources, KeyingSet *ks, short mode, float cfra)
+{
+ KS_Path *ksp;
+ int kflag, success= 0;
+ char *groupname= NULL;
+
+ /* get flags to use */
+ if (mode == COMMONKEY_MODE_INSERT) {
+ /* use KeyingSet's flags as base */
+ kflag= ks->keyingflag;
+
+ /* suppliment with info from the context */
+ if (IS_AUTOKEY_FLAG(AUTOMATKEY)) kflag |= INSERTKEY_MATRIX;
+ if (IS_AUTOKEY_FLAG(INSERTNEEDED)) kflag |= INSERTKEY_NEEDED;
+ // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
+ }
+ else if (mode == COMMONKEY_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.
+ */
+ for (ksp= ks->paths.first; ksp; ksp= ksp->next) {
+ /* get pointer to name of group to add channels to */
+ if (ksp->flag & KSP_FLAG_GROUP_NONE)
+ groupname= NULL;
+ else if (ksp->flag & KSP_FLAG_GROUP_KSNAME)
+ groupname= ks->name;
+ else
+ groupname= ksp->group;
+
+ /* action to take depends on mode */
+ if (mode == COMMONKEY_MODE_INSERT)
+ success+= insertkey(ksp->id, groupname, ksp->rna_path, ksp->array_index, cfra, kflag);
+ else if (mode == COMMONKEY_MODE_DELETE)
+ success+= deletekey(ksp->id, groupname, ksp->rna_path, ksp->array_index, cfra, kflag);
+ }
+ }
+#if 0 // XXX still need to figure out how to get such keyingsets working
+ else if (dsources) {
+ /* for each one of the 'sources', resolve the template markers and expand arrays, then insert keyframes */
+ bCommonKeySrc *cks;
+ char *path = NULL;
+ int index=0, tot=0;
+
+ /* for each 'source' for keyframe data, resolve each of the paths from the KeyingSet */
+ for (cks= dsources->first; cks; cks= cks->next) {
+
+ }
+ }
+#endif // XXX still need to figure out how to get such
+
+ return success;
+}
+
/* Insert Key Operator ------------------------ */
/* XXX WARNING:
@@ -2046,15 +2062,49 @@ void common_modifykey (bContext *C, short mode)
/* defines for basic insert-key testing operator */
// XXX this will definitely be replaced
EnumPropertyItem prop_insertkey_types[] = {
- {0, "OBLOC", "Object Location", ""},
- {1, "OBROT", "Object Rotation", ""},
- {2, "OBSCALE", "Object Scale", ""},
- {3, "MAT_COL", "Active Material - Color", ""},
- {4, "PCHANLOC", "Pose-Channel Location", ""},
- {5, "PCHANROT", "Pose-Channel Rotation", ""},
- {6, "PCHANSCALE", "Pose-Channel Scale", ""},
+ {0, "KEYINGSET", "Active KeyingSet", ""},
+ {1, "OBLOC", "Object Location", ""},
+ {2, "OBROT", "Object Rotation", ""},
+ {3, "OBSCALE", "Object Scale", ""},
+ {4, "MAT_COL", "Active Material - Color", ""},
+ {5, "PCHANLOC", "Pose-Channel Location", ""},
+ {6, "PCHANROT", "Pose-Channel Rotation", ""},
+ {7, "PCHANSCALE", "Pose-Channel Scale", ""},
{0, NULL, NULL, NULL}
};
+
+static int insert_key_invoke (bContext *C, wmOperator *op, wmEvent *event)
+{
+ Object *ob= CTX_data_active_object(C);
+ uiMenuItem *head;
+
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ head= uiPupMenuBegin("Insert Keyframe", 0);
+
+ /* active keyingset */
+ uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe", "type", 0);
+
+ /* selective inclusion */
+ if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
+ /* bone types */
+ uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe", "type", 5);
+ uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe", "type", 6);
+ uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe", "type", 7);
+ }
+ else {
+ /* object types */
+ uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe", "type", 1);
+ uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe", "type", 2);
+ uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe", "type", 3);
+ uiMenuItemEnumO(head, "", 0, "ANIM_OT_insert_keyframe", "type", 4);
+ }
+
+ uiPupMenuEnd(C, head);
+
+ return OPERATOR_CANCELLED;
+}
static int insert_key_exec (bContext *C, wmOperator *op)
{
@@ -2062,6 +2112,34 @@ static int insert_key_exec (bContext *C, wmOperator *op)
short mode= RNA_enum_get(op->ptr, "type");
float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
+ /* for now, handle 'active keyingset' one separately */
+ if (mode == 0) {
+ ListBase dsources = {NULL, NULL};
+ KeyingSet *ks= NULL;
+ short success;
+
+ /* try to get KeyingSet */
+ if (scene->active_keyingset > 0)
+ ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
+ /* report failure */
+ if (ks == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active Keying Set");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* try to insert keyframes for the channels specified by KeyingSet */
+ success= commonkey_modifykey(&dsources, ks, COMMONKEY_MODE_INSERT, cfra);
+ printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success);
+
+ /* report failure */
+ if (success == 0) {
+ BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes");
+ return OPERATOR_CANCELLED; // XXX?
+ }
+ else
+ return OPERATOR_FINISHED;
+ }
+
// XXX more comprehensive tests will be needed
CTX_DATA_BEGIN(C, Base*, base, selected_bases)
{
@@ -2073,24 +2151,24 @@ static int insert_key_exec (bContext *C, wmOperator *op)
if (mode < 4) {
/* object-based keyframes */
switch (mode) {
- case 3: /* color of active material (only for geometry...) */
+ case 4: /* color of active material (only for geometry...) */
// NOTE: this is just a demo... but ideally we'd go through materials instead of active one only so reference stays same
// XXX no group for now
success+= insertkey(id, NULL, "active_material.diffuse_color", 0, cfra, 0);
success+= insertkey(id, NULL, "active_material.diffuse_color", 1, cfra, 0);
success+= insertkey(id, NULL, "active_material.diffuse_color", 2, cfra, 0);
break;
- case 2: /* object scale */
+ case 3: /* object scale */
success+= insertkey(id, "Object Transforms", "scale", 0, cfra, 0);
success+= insertkey(id, "Object Transforms", "scale", 1, cfra, 0);
success+= insertkey(id, "Object Transforms", "scale", 2, cfra, 0);
break;
- case 1: /* object rotation */
+ case 2: /* object rotation */
success+= insertkey(id, "Object Transforms", "rotation", 0, cfra, 0);
success+= insertkey(id, "Object Transforms", "rotation", 1, cfra, 0);
success+= insertkey(id, "Object Transforms", "rotation", 2, cfra, 0);
break;
- default: /* object location */
+ case 1: /* object location */
success+= insertkey(id, "Object Transforms", "location", 0, cfra, 0);
success+= insertkey(id, "Object Transforms", "location", 1, cfra, 0);
success+= insertkey(id, "Object Transforms", "location", 2, cfra, 0);
@@ -2167,7 +2245,7 @@ void ANIM_OT_insert_keyframe (wmOperatorType *ot)
ot->idname= "ANIM_OT_insert_keyframe";
/* callbacks */
- ot->invoke= WM_menu_invoke; // XXX we will need our own one eventually, to cope with the dynamic menus...
+ ot->invoke= insert_key_invoke;
ot->exec= insert_key_exec;
ot->poll= ED_operator_areaactive;
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 91dbbec873f..e7441188fc3 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -31,6 +31,8 @@
struct ListBase;
struct ID;
+struct KeyingSet;
+
struct FCurve;
struct BezTriple;
@@ -81,6 +83,9 @@ short insertkey(struct ID *id, const char group[], const char rna_path[], int ar
short deletekey(struct ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag);
+/* Generate menu of KeyingSets */
+char *ANIM_build_keyingsets_menu(struct ListBase *list);
+
/* Main Keyframe Management operators:
* These handle keyframes management from various spaces. They will handle the menus
* required for each space.
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 9b3852e63bf..ccee97ad605 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -867,7 +867,7 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
offset += 17;
}
else {
- /* for ipo/constraint channels */
+ /* for normal channels */
UI_icon_draw(x+offset, yminc, special);
offset += 17;
}
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 7adb90e7464..8df483b9048 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -689,7 +689,6 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
int items, i;
/* build list of curves to draw */
- // XXX enable ANIMFILTER_CURVEVISIBLE when we have a method to set them
filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CURVESONLY|ANIMFILTER_CURVEVISIBLE);
items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@@ -1135,7 +1134,7 @@ void graph_draw_channel_names(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
offset += 17;
}
else {
- /* for ipo/constraint channels */
+ /* for normal channels */
UI_icon_draw(x+offset, yminc, special);
offset += 17;
}
diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c
index fbc475d3bdd..11d8cf50d4b 100644
--- a/source/blender/editors/space_outliner/outliner.c
+++ b/source/blender/editors/space_outliner/outliner.c
@@ -64,6 +64,7 @@
#include "IMB_imbuf_types.h"
+#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_deform.h"
@@ -3086,6 +3087,45 @@ void outliner_operation_menu(Scene *scene, ARegion *ar, SpaceOops *soops)
}
}
+/* ***************** KEYINGSET OPERATIONS *************** */
+
+/* These operators are only available in databrowser mode for now, as
+ * they depend on having RNA paths and/or hierarchies available.
+ */
+
+/* find the 'active' KeyingSet, and add if not found (if adding is allowed) */
+// TODO: should this be an API func?
+static KeyingSet *verify_active_keyingset(Scene *scene, short add)
+{
+ KeyingSet *ks= NULL;
+
+ /* try to find one from scene */
+ if (scene->active_keyingset > 0)
+ ks= BLI_findlink(&scene->keyingsets, scene->active_keyingset-1);
+
+ /* add if none found */
+ // XXX the default settings have yet to evolve
+ if ((add) && (ks==NULL))
+ ks= BKE_keyingset_add(&scene->keyingsets, "KeyingSet", KEYINGSET_ABSOLUTE, 0);
+
+ return ks;
+}
+
+/* ---------------------------------- */
+
+
+void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot)
+{
+
+}
+
+
+/* ---------------------------------- */
+
+void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot)
+{
+
+}
/* ***************** DRAW *************** */
diff --git a/source/blender/editors/space_outliner/outliner_header.c b/source/blender/editors/space_outliner/outliner_header.c
index 2c114f3099b..7add3f85ea0 100644
--- a/source/blender/editors/space_outliner/outliner_header.c
+++ b/source/blender/editors/space_outliner/outliner_header.c
@@ -44,6 +44,7 @@
#include "BKE_main.h"
#include "BKE_screen.h"
+#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_util.h"
#include "ED_types.h"
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index e7e75833d43..067c14dc257 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -119,6 +119,8 @@ void outliner_select(struct SpaceOops *soops, struct ListBase *lb, int *index, s
void draw_outliner(const struct bContext *C);
void OUTLINER_OT_activate_click(struct wmOperatorType *ot);
+void OUTLINER_OT_keyingset_add_selected(struct wmOperatorType *ot);
+void OUTLINER_OT_keyingset_remove_selected(struct wmOperatorType *ot);
#if 0
extern void outliner_mouse_event(Scene *scene, ARegion *ar, SpaceOops *soops, short event);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 7d1155cb5d7..295d7ade97c 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -44,6 +44,9 @@
void outliner_operatortypes(void)
{
WM_operatortype_append(OUTLINER_OT_activate_click);
+
+ WM_operatortype_append(OUTLINER_OT_keyingset_add_selected);
+ WM_operatortype_append(OUTLINER_OT_keyingset_remove_selected);
}
void outliner_keymap(wmWindowManager *wm)
@@ -51,6 +54,10 @@ void outliner_keymap(wmWindowManager *wm)
ListBase *keymap= WM_keymap_listbase(wm, "Outliner", SPACE_OOPS, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_activate_click", LEFTMOUSE, KM_PRESS, 0, 0);
+
+ /* keying sets - only for databrowse */
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_add_selected", KKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_remove_selected", KKEY, KM_PRESS, KM_ALT, 0);
}
diff --git a/source/blender/editors/space_time/time_header.c b/source/blender/editors/space_time/time_header.c
index 65946a4288b..1f03530b680 100644
--- a/source/blender/editors/space_time/time_header.c
+++ b/source/blender/editors/space_time/time_header.c
@@ -43,6 +43,7 @@
#include "BKE_global.h"
#include "BKE_screen.h"
+#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_types.h"
#include "ED_util.h"
@@ -429,6 +430,7 @@ void time_header_buttons(const bContext *C, ARegion *ar)
Scene *scene= CTX_data_scene(C);
uiBlock *block;
int xco, yco= 3;
+ char *menustr= NULL;
block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS, UI_HELV);
uiBlockSetHandleFunc(block, do_time_buttons, NULL);
@@ -539,12 +541,21 @@ void time_header_buttons(const bContext *C, ARegion *ar)
xco+= 16;
- uiDefIconBut(block, BUT, B_TL_INSERTKEY, ICON_KEY_HLT,
- xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Insert Keyframe for the context of the largest area (IKEY)");
- xco+= XIC+4;
+
+ menustr= ANIM_build_keyingsets_menu(&scene->keyingsets);
+ uiDefButI(block, MENU, B_DIFF,
+ menustr,
+ xco, yco, (int)5.5*XIC, YIC, &(scene->active_keyingset), 0, 1, 0, 0,
+ "Active Keying Set (i.e. set of channels to Insert Keyframes for)");
+ MEM_freeN(menustr);
+ xco+= (6*XIC);
+
uiDefIconBut(block, BUT, B_TL_DELETEKEY, ICON_KEY_DEHLT,
xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Delete Keyframe for the context of the largest area (ALTKEY-IKEY)");
xco+= XIC+4;
+ uiDefIconBut(block, BUT, B_TL_INSERTKEY, ICON_KEY_HLT,
+ xco, yco, XIC, YIC, 0, 0, 0, 0, 0, "Insert Keyframe for the context of the largest area (IKEY)");
+ xco+= XIC+4;
xco+= 16;
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 556d52e4aff..c1c5dec52a7 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -78,6 +78,7 @@
#include "ED_armature.h"
#include "ED_curve.h"
#include "ED_editparticle.h"
+#include "ED_keyframing.h"
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 17a552ad7e0..68564b1ee73 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -421,6 +421,77 @@ enum {
NLATRACK_TWEAK = (1<<5),
} eNlaTrack_Flag;
+
+/* ************************************ */
+/* KeyingSet Datatypes */
+
+/* Path for use in KeyingSet definitions (ksp)
+ *
+ * Paths may be either specific (specifying the exact sub-ID
+ * dynamic data-block - such as PoseChannels - to act upon, ala
+ * Maya's 'Character Sets' and XSI's 'Marking Sets'), or they may
+ * be generic (using various placeholder template tags that will be
+ * replaced with appropriate information from the context).
+ */
+// TODO: how should templates work exactly? For now, we only implement the specific KeyingSets...
+typedef struct KS_Path {
+ struct KS_Path *next, *prev;
+
+ /* absolute paths only */
+ ID *id; /* ID block that keyframes are for */
+ char group[64]; /* name of the group to add to */
+
+ /* all paths */
+ char *rna_path; /* dynamically (or statically in the case of predefined sets) path */
+ int array_index; /* index that path affects */
+
+ int flag; /* various settings, etc. */
+} KS_Path;
+
+/* KS_Path->flag */
+enum {
+ /* entire array (not just the specified index) gets keyframed */
+ KSP_FLAG_WHOLE_ARRAY = (1<<0),
+
+ /* path should not be grouped at all */
+ KSP_FLAG_GROUP_NONE = (1<<10),
+ /* path should be grouped under an ActionGroup KeyingSet's name */
+ KSP_FLAG_GROUP_KSNAME = (1<<11),
+} eKSP_Settings;
+
+/* ---------------- */
+
+/* KeyingSet definition (ks)
+ *
+ * A KeyingSet defines a group of properties that should
+ * be keyframed together, providing a convenient way for animators
+ * to insert keyframes without resorting to Auto-Keyframing.
+ *
+ * A few 'generic' (non-absolute and dependant on templates) KeyingSets
+ * are defined 'built-in' to facilitate easy animating for the casual
+ * animator without the need to add extra steps to the rigging process.
+ */
+typedef struct KeyingSet {
+ struct KeyingSet *next, *prev;
+
+ ListBase paths; /* (KS_Path) paths to keyframe to */
+
+ char name[64]; /* user-viewable name for KeyingSet (for menus, etc.) */
+
+ int flag; /* settings for KeyingSet */
+ int keyingflag; /* settings to supply insertkey() with */
+} KeyingSet;
+
+/* KeyingSet settings */
+enum {
+ /* keyingset cannot be removed (and doesn't need to be freed) */
+ KEYINGSET_BUILTIN = (1<<0),
+ /* keyingset is the one currently in use */
+ KEYINGSET_ACTIVE = (1<<1),
+ /* keyingset does not depend on context info (i.e. paths are absolute) */
+ KEYINGSET_ABSOLUTE = (1<<2),
+} eKS_Settings;
+
/* ************************************************ */
/* Animation Data */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index ac3f7e69399..7b618502089 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -537,7 +537,7 @@ typedef struct Scene {
short proportional, prop_mode;
short automerge, pad5, pad6;
- short autokey_mode; /* mode for autokeying (defines in DNA_userdef_types.h */
+ short autokey_mode; /* mode for autokeying (defines in DNA_userdef_types.h) */
short use_nodes;
@@ -571,7 +571,10 @@ typedef struct Scene {
/* frame step. */
int frame_step;
- int pad;
+
+ /* User-Defined KeyingSets */
+ int active_keyingset; /* index of the active KeyingSet. first KeyingSet has index 1 */
+ ListBase keyingsets; /* KeyingSets for the given frame */
} Scene;