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>2009-04-13 06:40:56 +0400
committerJoshua Leung <aligorith@gmail.com>2009-04-13 06:40:56 +0400
commitb27436af7c6956be1de46e7903ab96562f080469 (patch)
treec8c642c53b52672c0ad41fb7727f0d2f4f3fd37d /source/blender/editors/animation/keyingsets.c
parentf0fea321291e1dfc1bc070a4546f719c57b24a87 (diff)
2.5 - Separated Keying Sets code out into its own file
Diffstat (limited to 'source/blender/editors/animation/keyingsets.c')
-rw-r--r--source/blender/editors/animation/keyingsets.c1128
1 files changed, 1128 insertions, 0 deletions
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
new file mode 100644
index 00000000000..513e1bf5b21
--- /dev/null
+++ b/source/blender/editors/animation/keyingsets.c
@@ -0,0 +1,1128 @@
+/* Testing code for 2.5 animation system
+ * Copyright 2009, Joshua Leung
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_dynstr.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_key_types.h"
+#include "DNA_object_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_constraint.h"
+#include "BKE_fcurve.h"
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
+#include "BKE_report.h"
+#include "BKE_key.h"
+#include "BKE_material.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframing.h"
+#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "anim_intern.h"
+
+/* ************************************************** */
+/* KEYING SETS - EDITING API */
+
+/* Operators ------------------------------------------- */
+
+/* These operators are only provided for scripting/macro usage, not for direct
+ * calling from the UI since they wrap some of the data-access API code for these
+ * (defined in blenkernel) which have quite a few properties.
+ */
+
+/* ----- */
+
+static int keyingset_add_destination_exec (bContext *C, wmOperator *op)
+{
+ PointerRNA ptr;
+ KeyingSet *ks= NULL;
+ ID *id= NULL;
+ char rna_path[256], group_name[64]; // xxx
+ short groupmode=0, flag=0;
+ int array_index=0;
+
+ /* get settings from operator properties */
+ ptr = RNA_pointer_get(op->ptr, "keyingset");
+ if (ptr.data)
+ ks= (KeyingSet *)ptr.data;
+
+ ptr = RNA_pointer_get(op->ptr, "id");
+ if (ptr.data)
+ id= (ID *)ptr.data;
+
+ groupmode= RNA_enum_get(op->ptr, "grouping_method");
+ RNA_string_get(op->ptr, "group_name", group_name);
+
+ RNA_string_get(op->ptr, "rna_path", rna_path);
+ array_index= RNA_int_get(op->ptr, "array_index");
+
+ if (RNA_boolean_get(op->ptr, "entire_array"))
+ flag |= KSP_FLAG_WHOLE_ARRAY;
+
+ /* if enough args are provided, call API method */
+ if (ks) {
+ BKE_keyingset_add_destination(ks, id, group_name, rna_path, array_index, flag, groupmode);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Keying Set could not be added.");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void ANIM_OT_keyingset_add_destination (wmOperatorType *ot)
+{
+ // XXX: this is also defined in rna_animation.c
+ static EnumPropertyItem prop_mode_grouping_items[] = {
+ {KSP_GROUP_NAMED, "NAMED", "Named Group", ""},
+ {KSP_GROUP_NONE, "NONE", "None", ""},
+ {KSP_GROUP_KSNAME, "KEYINGSET", "Keying Set Name", ""},
+ {0, NULL, NULL, NULL}};
+
+ /* identifiers */
+ ot->name= "Add Keying Set Destination";
+ ot->idname= "ANIM_OT_keyingset_add_destination";
+
+ /* callbacks */
+ ot->exec= keyingset_add_destination_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* props */
+ /* pointers */ // xxx - do we want to directly expose these?
+ RNA_def_pointer_runtime(ot->srna, "keyingset", &RNA_KeyingSet, "Keying Set", "Keying Set to add destination to.");
+ RNA_def_pointer_runtime(ot->srna, "id", &RNA_ID, "ID", "ID-block for the destination.");
+ /* grouping */
+ RNA_def_enum(ot->srna, "grouping_method", prop_mode_grouping_items, KSP_GROUP_NAMED, "Grouping Method", "Method used to define which Group-name to use.");
+ RNA_def_string(ot->srna, "group_name", "", 64, "Group Name", "Name of Action Group to assign destination to (only if grouping mode is to use this name).");
+ /* rna-path */
+ RNA_def_string(ot->srna, "rna_path", "", 256, "RNA-Path", "RNA-Path to destination property."); // xxx hopefully this is long enough
+ RNA_def_int(ot->srna, "array_index", 0, 0, INT_MAX, "Array Index", "If applicable, the index ", 0, INT_MAX);
+ /* flags */
+ RNA_def_boolean(ot->srna, "entire_array", 1, "Entire Array", "hen an 'array/vector' type is chosen (Location, Rotation, Color, etc.), entire array is to be used.");
+
+}
+
+/* ----- */
+
+static int keyingset_add_new_exec (bContext *C, wmOperator *op)
+{
+ Scene *sce= CTX_data_scene(C);
+ KeyingSet *ks= NULL;
+ short flag=0, keyingflag=0;
+ char name[64];
+
+ /* get settings from operator properties */
+ RNA_string_get(op->ptr, "name", name);
+
+ if (RNA_boolean_get(op->ptr, "absolute"))
+ flag |= KEYINGSET_ABSOLUTE;
+ if (RNA_boolean_get(op->ptr, "insertkey_needed"))
+ keyingflag |= INSERTKEY_NEEDED;
+ if (RNA_boolean_get(op->ptr, "insertkey_visual"))
+ keyingflag |= INSERTKEY_MATRIX;
+
+ /* call the API func, and set the active keyingset index */
+ ks= BKE_keyingset_add(&sce->keyingsets, name, flag, keyingflag);
+
+ if (ks) {
+ sce->active_keyingset= BLI_countlist(&sce->keyingsets);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Keying Set could not be added.");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void ANIM_OT_keyingset_add_new (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Keying Set";
+ ot->idname= "ANIM_OT_keyingset_add_new";
+
+ /* callbacks */
+ ot->exec= keyingset_add_new_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* props */
+ /* name */
+ RNA_def_string(ot->srna, "name", "KeyingSet", 64, "Name", "Name of Keying Set");
+ /* flags */
+ RNA_def_boolean(ot->srna, "absolute", 1, "Absolute", "Keying Set defines specific paths/settings to be keyframed (i.e. is not reliant on context info)");
+ /* keying flags */
+ RNA_def_boolean(ot->srna, "insertkey_needed", 0, "Insert Keyframes - Only Needed", "Only insert keyframes where they're needed in the relevant F-Curves.");
+ RNA_def_boolean(ot->srna, "insertkey_visual", 0, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'.");
+}
+
+/* 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 Active>%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)}
+
+/* --- */
+
+/* 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;
+}
+
+/* Object KeyingSets ------ */
+
+/* check if include shapekey entry */
+static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
+{
+ //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;
+
+ /* 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;
+
+ /* not geometry! */
+ default:
+ return 0;
+ }
+
+ /* 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;
+}
+
+/* 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[] =
+{
+ /* 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}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {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}},
+
+ {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
+
+ {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);
+}
+
+/* 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[] =
+{
+ /* 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
+
+
+ {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}},
+
+ {NULL, "%l", 0, -1, 0, {0}}, // separator
+
+ {NULL, "Available", ID_CA, -2, 0, {0}}
+};
+
+/* --- */
+
+/* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
+bKeyingContext ks_contexts[] =
+{
+ KSC_TEMPLATE(v3d_object),
+ KSC_TEMPLATE(v3d_pchan),
+
+ 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.
+ */
+
+/* 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(name, keyingflag) \
+ {NULL, NULL, {NULL, NULL}, name, KEYINGSET_BUILTIN, keyingflag}
+
+/* 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 \
+ }
+
+/* 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}
+
+/* ---- */
+
+/* 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" ---------- */
+ {
+ /* KeyingSet Definition */
+ BI_KS_DEFINE("Location", 0),
+
+ /* Path Definitions */
+ BI_KS_PATHS_BEGIN(1)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_KSNAME)
+ BI_KS_PATHS_END
+ },
+
+ /* Keying Set - "Rotation" ---------- */
+ {
+ /* KeyingSet Definition */
+ BI_KS_DEFINE("Rotation", 0),
+
+ /* Path Definitions */
+ BI_KS_PATHS_BEGIN(1)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_KSNAME)
+ BI_KS_PATHS_END
+ },
+
+ /* Keying Set - "Scaling" ---------- */
+ {
+ /* KeyingSet Definition */
+ BI_KS_DEFINE("Scaling", 0),
+
+ /* Path Definitions */
+ BI_KS_PATHS_BEGIN(1)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_KSNAME)
+ BI_KS_PATHS_END
+ },
+
+ /* Compound Keying Sets *********************************** */
+ /* Keying Set - "LocRot" ---------- */
+ {
+ /* KeyingSet Definition */
+ BI_KS_DEFINE("LocRot", 0),
+
+ /* Path Definitions */
+ BI_KS_PATHS_BEGIN(2)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_KSNAME),
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_KSNAME)
+ BI_KS_PATHS_END
+ },
+
+ /* Keying Set - "LocRotScale" ---------- */
+ {
+ /* KeyingSet Definition */
+ BI_KS_DEFINE("LocRotScale", 0),
+
+ /* Path Definitions */
+ BI_KS_PATHS_BEGIN(2)
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_KSNAME),
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_KSNAME),
+ BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_KSNAME)
+ BI_KS_PATHS_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);
+ }
+ }
+}
+
+/* ******************************************* */
+/* KEYFRAME MODIFICATION */
+
+/* KeyingSet Menu Helpers ------------ */
+
+/* Extract the maximum set of requirements from the KeyingSet */
+static int keyingset_relative_get_templates (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;
+ }
+
+ return templates;
+}
+
+/* Check if context data is suitable for the given absolute Keying Set */
+short keyingset_context_ok_poll (bContext *C, KeyingSet *ks)
+{
+ ScrArea *sa= CTX_wm_area(C);
+
+ /* data retrieved from context depends on active editor */
+ if (sa == NULL) return 0;
+
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ Object *obact= CTX_data_active_object(C);
+
+ /* if in posemode, check if 'pose-channels' requested for in KeyingSet */
+ if ((obact && obact->pose) && (obact->flag & OB_POSEMODE)) {
+ /* check for posechannels */
+
+ }
+ else {
+ /* check for selected object */
+
+ }
+ }
+ break;
+ }
+
+
+ return 1;
+}
+
+/* KeyingSet Context Operations ------------ */
+
+/* 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)
+{
+ 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->flag & OB_POSEMODE)) {
+ /* 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_pchans)
+ {
+ /* 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, Base*, base, selected_bases)
+ {
+ Object *ob= base->object;
+
+ /* 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;
+ }
+
+ /* return whether any data was extracted */
+ return ok;
+}
+
+/* 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)
+{
+ ScrArea *sa= CTX_wm_area(C);
+
+ /* for now, the active area is used to determine what set of contexts apply */
+ if (sa == NULL)
+ return 0;
+
+ switch (sa->spacetype) {
+ case SPACE_VIEW3D: /* 3D-View: Selected Objects or Bones */
+ return modifykey_get_context_v3d_data(C, dsources, ks);
+ }
+
+ /* nothing happened */
+ return 0;
+}
+
+/* KeyingSet Operations (Insert/Delete Keyframes) ------------ */
+
+/* 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
+ */
+int modify_keyframes (bContext *C, ListBase *dsources, KeyingSet *ks, short mode, float cfra)
+{
+ KS_Path *ksp;
+ int kflag=0, success= 0;
+ char *groupname= NULL;
+
+ /* get flags to use */
+ if (mode == MODIFYKEY_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 == 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.
+ */
+ 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+1;
+
+ /* 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);
+ }
+
+ /* 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+= insertkey(ksp->id, groupname, ksp->rna_path, i, cfra, kflag);
+ else if (mode == MODIFYKEY_MODE_DELETE)
+ success+= deletekey(ksp->id, groupname, ksp->rna_path, i, cfra, kflag);
+ }
+
+ /* send notifiers and set recalc-flags */
+ // TODO: hopefully this doesn't result in execessive flooding of the notifier stack
+ if (C && ksp->id) {
+ switch (GS(ksp->id->name)) {
+ case ID_OB: /* Object (or Object-Related) Keyframes */
+ {
+ Object *ob= (Object *)ksp->id;
+
+ ob->recalc |= OB_RECALC;
+ WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, ksp->id);
+ }
+ break;
+ case ID_MA: /* Material Keyframes */
+ WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, ksp->id);
+ break;
+ }
+ }
+ }
+ }
+ else if (dsources && dsources->first) {
+ /* for each one of the 'sources', resolve the template markers and expand arrays, then insert keyframes */
+ bCommonKeySrc *cks;
+
+ /* 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;
+
+ /* 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.pose_channels[\"");
+ BLI_dynstr_append(pathds, cks->pchan->name);
+ BLI_dynstr_append(pathds, "\"]");
+ }
+ 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, "\"]");
+ }
+ {
+ /* add property stored in KeyingSet Path */
+ if (BLI_dynstr_get_len(pathds))
+ BLI_dynstr_append(pathds, ".");
+ 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 */
+ 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+1;
+
+ /* 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(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+= insertkey(cks->id, groupname, path, i, cfra, kflag);
+ else if (mode == MODIFYKEY_MODE_DELETE)
+ success+= deletekey(cks->id, groupname, path, i, cfra, kflag);
+ }
+
+ /* free the path */
+ MEM_freeN(path);
+ }
+
+ /* send notifiers and set recalc-flags */
+ // TODO: hopefully this doesn't result in execessive flooding of the notifier stack
+ if (C && cks->id) {
+ switch (GS(cks->id->name)) {
+ case ID_OB: /* Object (or Object-Related) Keyframes */
+ {
+ Object *ob= (Object *)cks->id;
+
+ ob->recalc |= OB_RECALC;
+ WM_event_add_notifier(C, NC_OBJECT|ND_KEYS, cks->id);
+ }
+ break;
+ case ID_MA: /* Material Keyframes */
+ WM_event_add_notifier(C, NC_MATERIAL|ND_KEYS, cks->id);
+ break;
+ }
+ }
+ }
+ }
+
+ /* return the number of channels successfully affected */
+ return success;
+}
+
+/* ************************************************** */