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--release/scripts/keyingsets/keyingsets_builtins.py236
-rw-r--r--release/scripts/keyingsets/keyingsets_utils.py170
-rw-r--r--release/scripts/modules/bpy/utils.py4
-rw-r--r--source/blender/blenkernel/BKE_animsys.h5
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c67
-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
-rw-r--r--source/blender/makesdna/DNA_anim_types.h10
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_animation.c270
-rw-r--r--source/blender/makesrna/intern/rna_animation_api.c39
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c6
21 files changed, 1269 insertions, 1313 deletions
diff --git a/release/scripts/keyingsets/keyingsets_builtins.py b/release/scripts/keyingsets/keyingsets_builtins.py
new file mode 100644
index 00000000000..c5417ba3d66
--- /dev/null
+++ b/release/scripts/keyingsets/keyingsets_builtins.py
@@ -0,0 +1,236 @@
+# Built-In Keying Sets
+# None of these Keying Sets should be removed, as these
+# are needed by various parts of Blender in order for them
+# to work correctly.
+
+import bpy
+from keyingsets_utils import *
+
+###############################
+# Built-In KeyingSets
+
+# Location
+class BUILTIN_KSI_Location(bpy.types.KeyingSetInfo):
+ bl_idname = "Location"
+ bl_builtin = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ generate = RKS_GEN_location
+
+# Rotation
+class BUILTIN_KSI_Rotation(bpy.types.KeyingSetInfo):
+ bl_idname = "Rotation"
+ bl_builtin = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ generate = RKS_GEN_rotation
+
+# Scale
+class BUILTIN_KSI_Scaling(bpy.types.KeyingSetInfo):
+ bl_idname = "Scaling"
+ bl_builtin = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ generate = RKS_GEN_scaling
+
+# ------------
+
+# LocRot
+class BUILTIN_KSI_LocRot(bpy.types.KeyingSetInfo):
+ bl_idname = "LocRot"
+ bl_builtin = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ def generate(self, context, ks, data):
+ # location
+ RKS_GEN_location(self, context, ks, data)
+ # rotation
+ RKS_GEN_rotation(self, context, ks, data)
+
+# LocScale
+class BUILTIN_KSI_LocScale(bpy.types.KeyingSetInfo):
+ bl_idname = "LocScale"
+ bl_builtin = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ def generate(self, context, ks, data):
+ # location
+ RKS_GEN_location(self, context, ks, data)
+ # scale
+ RKS_GEN_scaling(self, context, ks, data)
+
+# LocRotScale
+class BUILTIN_KSI_LocRotScale(bpy.types.KeyingSetInfo):
+ bl_idname = "LocRotScale"
+ bl_builtin = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ def generate(self, context, ks, data):
+ # location
+ RKS_GEN_location(self, context, ks, data)
+ # rotation
+ RKS_GEN_rotation(self, context, ks, data)
+ # scale
+ RKS_GEN_scaling(self, context, ks, data)
+
+# RotScale
+class BUILTIN_KSI_RotScale(bpy.types.KeyingSetInfo):
+ bl_idname = "RotScale"
+ bl_builtin = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ def generate(self, context, ks, data):
+ # rotation
+ RKS_GEN_rotation(self, context, ks, data)
+ # scaling
+ RKS_GEN_scaling(self, context, ks, data)
+
+# ------------
+
+# Location
+class BUILTIN_KSI_VisualLoc(bpy.types.KeyingSetInfo):
+ bl_idname = "Visual Location"
+ bl_builtin = True
+
+ insertkey_visual = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ generate = RKS_GEN_location
+
+# Rotation
+class BUILTIN_KSI_VisualRot(bpy.types.KeyingSetInfo):
+ bl_idname = "Visual Rotation"
+ bl_builtin = True
+
+ insertkey_visual = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ generate = RKS_GEN_rotation
+
+# VisualLocRot
+class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo):
+ bl_idname = "Visual LocRot"
+ bl_builtin = True
+
+ insertkey_visual = True
+
+ # poll - use predefined callback for selected bones/objects
+ poll = RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ def generate(self, context, ks, data):
+ # location
+ RKS_GEN_location(self, context, ks, data)
+ # rotation
+ RKS_GEN_rotation(self, context, ks, data)
+
+# ------------
+
+# Available
+class BUILTIN_KSI_Available(bpy.types.KeyingSetInfo):
+ bl_idname = "Available"
+ bl_builtin = True
+
+ # poll - use predefined callback for selected objects
+ # TODO: this should really check whether the selected object (or datablock)
+ # has any animation data defined yet
+ poll = RKS_POLL_selected_objects
+
+ # iterator - use callback for selected bones/objects
+ iterator = RKS_ITER_selected_item
+
+ # generator - use callback for location
+ generate = RKS_GEN_available
+
+###############################
+
+classes = [
+ BUILTIN_KSI_Location,
+ BUILTIN_KSI_Rotation,
+ BUILTIN_KSI_Scaling,
+
+ BUILTIN_KSI_LocRot,
+ BUILTIN_KSI_LocScale,
+ BUILTIN_KSI_LocRotScale,
+ BUILTIN_KSI_RotScale,
+
+ BUILTIN_KSI_VisualLoc,
+ BUILTIN_KSI_VisualRot,
+ BUILTIN_KSI_VisualLocRot,
+
+ BUILTIN_KSI_Available,
+]
+
+
+def register():
+ register = bpy.types.register
+ for cls in classes:
+ register(cls)
+
+
+def unregister():
+ unregister = bpy.types.unregister
+ for cls in classes:
+ unregister(cls)
+
+if __name__ == "__main__":
+ register()
+
+###############################
diff --git a/release/scripts/keyingsets/keyingsets_utils.py b/release/scripts/keyingsets/keyingsets_utils.py
new file mode 100644
index 00000000000..78e170c88f9
--- /dev/null
+++ b/release/scripts/keyingsets/keyingsets_utils.py
@@ -0,0 +1,170 @@
+# This file defines a set of methods that are useful for various
+# Relative Keying Set (RKS) related operations, such as: callbacks
+# for polling, iterator callbacks, and also generate callbacks.
+# All of these can be used in conjunction with the others.
+
+import bpy
+
+###########################
+# General Utilities
+
+# Append the specified property name on the the existing path
+def path_add_property(path, prop):
+ if len(path):
+ return path + "." + prop;
+ else:
+ return prop;
+
+###########################
+# Poll Callbacks
+
+# selected objects
+def RKS_POLL_selected_objects(ksi, context):
+ return context.active_object or len(context.selected_objects);
+
+# selected bones
+def RKS_POLL_selected_bones(ksi, context):
+ # we must be in Pose Mode, and there must be some bones selected
+ if (context.active_object) and (context.active_object.mode == 'POSE'):
+ if context.active_pose_bone or len(context.select_pose_bones):
+ return True;
+
+ # nothing selected
+ return False;
+
+
+# selected bones or objects
+def RKS_POLL_selected_items(ksi, context):
+ return RKS_POLL_selected_bones(ksi, context) or RKS_POLL_selected_objects(ksi, context);
+
+###########################
+# Iterator Callbacks
+
+# all selected objects or pose bones, depending on which we've got
+def RKS_ITER_selected_item(ksi, context, ks):
+ if (context.active_object) and (context.active_object.mode == 'POSE'):
+ for bone in context.selected_pose_bones:
+ ksi.generate(context, ks, bone)
+ else:
+ for ob in context.selected_objects:
+ ksi.generate(context, ks, ob)
+
+###########################
+# Generate Callbacks
+
+# 'Available' F-Curves
+def RKS_GEN_available(ksi, context, ks, data):
+ # try to get the animation data associated with the closest
+ # ID-block to the data (neither of which may exist/be easy to find)
+ id_block = data.id_data
+ try:
+ adt = id_block.animation_data
+ except:
+ # there isn't any animation data available
+ return;
+
+ # there must also be an active action...
+ if adt.action is None:
+ return;
+
+ # for each F-Curve, include an path to key it
+ # NOTE: we don't need to set the group settings here
+ for fcu in adt.action.fcurves:
+ ks.add_path(id_block, fcu.rna_path, array_index=fcu.array_index, entire_array=False)
+
+# ------
+
+# get ID block and based ID path for transform generators
+def get_transform_generators_base_info(data):
+ # ID-block for the data
+ id_block = data.id_data
+
+ # get base path and grouping method/name
+ if isinstance(data, bpy.types.ID):
+ # no path in this case
+ path = ""
+
+ # data on ID-blocks directly should get grouped by the KeyingSet
+ grouping = None;
+ else:
+ # get the path to the ID-block
+ path = data.path_to_id()
+
+ try:
+ # try to use the name of the data element to group the F-Curve
+ grouping = data.name
+ except:
+ # fallback on the KeyingSet name
+ grouping = None;
+
+ # return the ID-block and the path
+ return id_block, path, grouping
+
+# Location
+def RKS_GEN_location(ksi, context, ks, data):
+ # get id-block and path info
+ id_block, base_path, grouping= get_transform_generators_base_info(data)
+
+ # add the property name to the base path
+ path = path_add_property(base_path, "location")
+
+ # add Keying Set entry for this...
+ if grouping:
+ ks.add_path(id_block, path, grouping_method='NAMED', group_name=grouping)
+ else:
+ ks.add_path(id_block, path)
+
+# Rotation
+def RKS_GEN_rotation(ksi, context, ks, data):
+ # get id-block and path info
+ id_block, base_path, grouping= get_transform_generators_base_info(data)
+
+ # add the property name to the base path
+ # rotation mode affects the property used
+ if data.rotation_mode == 'QUATERNION':
+ path = path_add_property(base_path, "rotation_quaternion")
+ elif data.rotation_mode == 'AXISANGLE':
+ path = path_add_property(base_path, "rotation_axis_angle")
+ else:
+ path = path_add_property(base_path, "rotation_euler")
+
+ # add Keying Set entry for this...
+ if grouping:
+ ks.add_path(id_block, path, grouping_method='NAMED', group_name=grouping)
+ else:
+ ks.add_path(id_block, path)
+
+# Scaling
+def RKS_GEN_scaling(ksi, context, ks, data):
+ # get id-block and path info
+ id_block, base_path, grouping= get_transform_generators_base_info(data)
+
+ # add the property name to the base path
+ path = path_add_property(base_path, "scale")
+
+ # add Keying Set entry for this...
+ if grouping:
+ ks.add_path(id_block, path, grouping_method='NAMED', group_name=grouping)
+ else:
+ ks.add_path(id_block, path)
+
+###########################
+# Un-needed stuff which is here to just shut up the warnings...
+
+classes = []
+
+def register():
+ register = bpy.types.register
+ for cls in classes:
+ register(cls)
+
+
+def unregister():
+ unregister = bpy.types.unregister
+ for cls in classes:
+ unregister(cls)
+
+if __name__ == "__main__":
+ register()
+
+###########################
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py
index 7787d9ee5fe..5b0599fe25f 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -169,7 +169,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
_loaded[:] = []
for base_path in script_paths(user=False):
- for path_subdir in ("ui", "op", "io", "cfg"):
+ for path_subdir in ("ui", "op", "io", "cfg", "keyingsets"):
path = _os.path.join(base_path, path_subdir)
if _os.path.isdir(path):
sys_path_ensure(path)
@@ -179,7 +179,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
user_path = user_script_path()
if user_path:
- for path_subdir in ("", "ui", "op", "io", "cfg"):
+ for path_subdir in ("", "ui", "op", "io", "cfg", "keyingsets"):
path = _os.path.join(user_path, path_subdir)
if _os.path.isdir(path):
sys_path_ensure(path)
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index f6950ba07b8..8644074d4e9 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -71,7 +71,7 @@ void BKE_animdata_make_local(struct AnimData *adt);
struct KeyingSet *BKE_keyingset_add(struct ListBase *list, const char name[], short flag, short keyingflag);
/* Add a path to a KeyingSet */
-void BKE_keyingset_add_path(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode);
+struct KS_Path *BKE_keyingset_add_path(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode);
/* Find the destination matching the criteria given */
struct KS_Path *BKE_keyingset_find_path(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode);
@@ -79,6 +79,9 @@ struct KS_Path *BKE_keyingset_find_path(struct KeyingSet *ks, struct ID *id, con
/* Copy all KeyingSets in the given list */
void BKE_keyingsets_copy(struct ListBase *newlist, struct ListBase *list);
+/* Free the given Keying Set path */
+void BKE_keyingset_free_path(struct KeyingSet *ks, struct KS_Path *ksp);
+
/* Free data for KeyingSet but not set itself */
void BKE_keyingset_free(struct KeyingSet *ks);
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index a880417a111..8ec8f24d5fe 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -621,53 +621,48 @@ KeyingSet *BKE_keyingset_add (ListBase *list, const char name[], short flag, sho
return ks;
}
-/* Add a destination to a KeyingSet. Nothing is returned for now...
+/* Add a path 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_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode)
+KS_Path *BKE_keyingset_add_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode)
{
KS_Path *ksp;
/* sanity checks */
if ELEM(NULL, ks, rna_path) {
- printf("ERROR: no Keying Set and/or RNA Path to add destination with \n");
- return;
+ printf("ERROR: no Keying Set and/or RNA Path to add path with \n");
+ return NULL;
}
- /* ID is optional for relative KeyingSets, but is necessary for absolute KeyingSets */
+ /* ID is required for all types of KeyingSets */
if (id == NULL) {
- if (ks->flag & KEYINGSET_ABSOLUTE) {
- printf("ERROR: No ID provided for absolute destination. \n");
- return;
- }
+ printf("ERROR: No ID provided for Keying Set Path. \n");
+ return NULL;
}
/* don't add if there is already a matching KS_Path in the KeyingSet */
if (BKE_keyingset_find_path(ks, id, group_name, rna_path, array_index, groupmode)) {
if (G.f & G_DEBUG)
printf("ERROR: destination already exists in Keying Set \n");
- return;
+ return NULL;
}
/* 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;
- if (group_name)
- BLI_snprintf(ksp->group, 64, group_name);
- else
- strcpy(ksp->group, "");
- }
+ ksp->id= id;
+ if (group_name)
+ BLI_snprintf(ksp->group, 64, group_name);
+ else
+ strcpy(ksp->group, "");
/* store additional info for relative paths (just in case user makes the set relative) */
if (id)
ksp->idtype= GS(id->name);
/* just copy path info */
- // XXX no checks are performed for templates yet
- // should array index be checked too?
+ // TODO: should array index be checked too?
ksp->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
ksp->array_index= array_index;
@@ -677,20 +672,37 @@ void BKE_keyingset_add_path (KeyingSet *ks, ID *id, const char group_name[], con
/* add KeyingSet path to KeyingSet */
BLI_addtail(&ks->paths, ksp);
+
+ /* return this path */
+ return ksp;
}
+/* Free the given Keying Set path */
+void BKE_keyingset_free_path (KeyingSet *ks, KS_Path *ksp)
+{
+ /* sanity check */
+ if ELEM(NULL, ks, ksp)
+ return;
+
+ /* free RNA-path info */
+ MEM_freeN(ksp->rna_path);
+
+ /* free path itself */
+ BLI_freelinkN(&ks->paths, ksp);
+}
+
/* Copy all KeyingSets in the given list */
-void BKE_keyingsets_copy(ListBase *newlist, ListBase *list)
+void BKE_keyingsets_copy (ListBase *newlist, ListBase *list)
{
KeyingSet *ksn;
KS_Path *kspn;
-
+
BLI_duplicatelist(newlist, list);
- for(ksn=newlist->first; ksn; ksn=ksn->next) {
+ for (ksn=newlist->first; ksn; ksn=ksn->next) {
BLI_duplicatelist(&ksn->paths, &ksn->paths);
-
- for(kspn=ksn->paths.first; kspn; kspn=kspn->next)
+
+ for (kspn=ksn->paths.first; kspn; kspn=kspn->next)
kspn->rna_path= MEM_dupallocN(kspn->rna_path);
}
}
@@ -709,12 +721,7 @@ void BKE_keyingset_free (KeyingSet *ks)
/* 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, ksp);
+ BKE_keyingset_free_path(ks, ksp);
}
}
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);
}
}
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index d2755f71fa3..8e46cfefba5 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -663,20 +663,19 @@ typedef enum eNlaTrack_Flag {
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 */
- /* relative paths only */
int idtype; /* ID-type that path can be used on */
- int templates; /* Templates that will be encountered in the path (as set of bitflags) */
- /* all paths */
+ short groupmode; /* group naming (eKSP_Grouping) */
+ short pad;
+
char *rna_path; /* dynamically (or statically in the case of predefined sets) path */
int array_index; /* index that path affects */
short flag; /* various settings, etc. */
- short groupmode; /* group naming (eKSP_Grouping) */
+ short keyingflag; /* settings to supply insertkey() with */
} KS_Path;
/* KS_Path->flag */
@@ -734,6 +733,7 @@ typedef struct KeyingSet {
ListBase paths; /* (KS_Path) paths to keyframe to */
char name[64]; /* user-viewable name for KeyingSet (for menus, etc.) */
+ char typeinfo[64]; /* name of the typeinfo data used for the relative paths */
short flag; /* settings for KeyingSet */
short keyingflag; /* settings to supply insertkey() with */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index ae431beb1fe..e50b1b7ad58 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -257,6 +257,7 @@ extern StructRNA RNA_KeyConfig;
extern StructRNA RNA_Keyframe;
extern StructRNA RNA_KeyingSet;
extern StructRNA RNA_KeyingSetPath;
+extern StructRNA RNA_KeyingSetInfo;
extern StructRNA RNA_KeyMap;
extern StructRNA RNA_KeyMapItem;
extern StructRNA RNA_KinematicConstraint;
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 453d9b9a844..e048a79daf8 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -37,12 +37,13 @@
#include "MEM_guardedalloc.h"
+#include "ED_keyframing.h"
+
/* exported for use in API */
EnumPropertyItem keyingset_path_grouping_items[] = {
{KSP_GROUP_NAMED, "NAMED", 0, "Named Group", ""},
{KSP_GROUP_NONE, "NONE", 0, "None", ""},
{KSP_GROUP_KSNAME, "KEYINGSET", 0, "Keying Set Name", ""},
- {KSP_GROUP_TEMPLATE_ITEM, "TEMPLATE", 0, "Innermost Context-Item Name", ""},
{0, NULL, 0, NULL, NULL}};
#ifdef RNA_RUNTIME
@@ -66,6 +67,152 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
/* ****************************** */
+/* wrapper for poll callback */
+static int RKS_POLL_rna_internal(KeyingSetInfo *ksi, bContext *C)
+{
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int ok;
+
+ RNA_pointer_create(NULL, ksi->ext.srna, ksi, &ptr);
+ func= RNA_struct_find_function(&ptr, "poll");
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ /* hook up arguments */
+ RNA_parameter_set_lookup(&list, "ksi", &ksi);
+ RNA_parameter_set_lookup(&list, "context", &C);
+
+ /* execute the function */
+ ksi->ext.call(&ptr, func, &list);
+
+ /* read the result */
+ RNA_parameter_get_lookup(&list, "ok", &ret);
+ ok= *(int*)ret;
+ RNA_parameter_list_free(&list);
+
+ return ok;
+}
+
+/* wrapper for iterator callback */
+static void RKS_ITER_rna_internal(KeyingSetInfo *ksi, bContext *C, KeyingSet *ks)
+{
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(NULL, ksi->ext.srna, ksi, &ptr);
+ func= RNA_struct_find_function(&ptr, "iterator");
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ /* hook up arguments */
+ RNA_parameter_set_lookup(&list, "ksi", &ksi);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "ks", &ks);
+
+ /* execute the function */
+ ksi->ext.call(&ptr, func, &list);
+ RNA_parameter_list_free(&list);
+}
+
+/* wrapper for generator callback */
+static void RKS_GEN_rna_internal(KeyingSetInfo *ksi, bContext *C, KeyingSet *ks, PointerRNA *data)
+{
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(NULL, ksi->ext.srna, ksi, &ptr);
+ func= RNA_struct_find_function(&ptr, "iterator");
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ /* hook up arguments */
+ RNA_parameter_set_lookup(&list, "ksi", &ksi);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "ks", &ks);
+ RNA_parameter_set_lookup(&list, "data", &data);
+
+ /* execute the function */
+ ksi->ext.call(&ptr, func, &list);
+ RNA_parameter_list_free(&list);
+}
+
+/* ------ */
+
+// XXX: the exact purpose of this is not too clear... maybe we want to revise this at some point?
+static StructRNA *rna_KeyingSetInfo_refine(PointerRNA *ptr)
+{
+ KeyingSetInfo *ksi= (KeyingSetInfo *)ptr->data;
+ return (ksi->ext.srna)? ksi->ext.srna: &RNA_KeyingSetInfo;
+}
+
+static void rna_KeyingSetInfo_unregister(const bContext *C, StructRNA *type)
+{
+ KeyingSetInfo *ksi= RNA_struct_blender_type_get(type);
+
+ if (ksi == NULL)
+ return;
+
+ /* free RNA data referencing this */
+ RNA_struct_free_extension(type, &ksi->ext);
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* unlink Blender-side data */
+ ANIM_keyingset_info_unregister(C, ksi);
+}
+
+static StructRNA *rna_KeyingSetInfo_register(const bContext *C, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ KeyingSetInfo dummyksi = {0};
+ KeyingSetInfo *ksi;
+ PointerRNA dummyptr;
+ int have_function[3];
+
+ /* setup dummy type info to store static properties in */
+ // TODO: perhaps we want to get users to register as if they're using 'KeyingSet' directly instead?
+ RNA_pointer_create(NULL, &RNA_KeyingSetInfo, &dummyksi, &dummyptr);
+
+ /* validate the python class */
+ if (validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if (strlen(identifier) >= sizeof(dummyksi.name)) {
+ BKE_reportf(reports, RPT_ERROR, "registering keying set info class: '%s' is too long, maximum length is %d.", identifier, sizeof(dummyksi.name));
+ return NULL;
+ }
+
+ /* check if we have registered this info before, and remove it */
+ ksi = ANIM_keyingset_info_find_named(dummyksi.name);
+ if (ksi && ksi->ext.srna)
+ rna_KeyingSetInfo_unregister(C, ksi->ext.srna);
+
+ /* create a new KeyingSetInfo type */
+ ksi= MEM_callocN(sizeof(KeyingSetInfo), "python keying set info");
+ memcpy(ksi, &dummyksi, sizeof(KeyingSetInfo));
+
+ /* set RNA-extensions info */
+ ksi->ext.srna= RNA_def_struct(&BLENDER_RNA, ksi->name, "KeyingSetInfo");
+ ksi->ext.data= data;
+ ksi->ext.call= call;
+ ksi->ext.free= free;
+ RNA_struct_blender_type_set(ksi->ext.srna, ksi);
+
+ /* set callbacks */
+ // NOTE: we really should have all of these...
+ ksi->poll= (have_function[0])? RKS_POLL_rna_internal: NULL;
+ ksi->iter= (have_function[1])? RKS_ITER_rna_internal: NULL;
+ ksi->generate= (have_function[2])? RKS_GEN_rna_internal: NULL;
+
+ /* add and register with other info as needed */
+ ANIM_keyingset_info_register(C, ksi);
+
+ /* return the struct-rna added */
+ return ksi->ext.srna;
+}
+
+/* ****************************** */
+
static StructRNA *rna_ksPath_id_typef(PointerRNA *ptr)
{
KS_Path *ksp= (KS_Path*)ptr->data;
@@ -123,6 +270,14 @@ static void rna_ksPath_RnaPath_set(PointerRNA *ptr, const char *value)
/* ****************************** */
+static int rna_KeyingSet_typeinfo_name_editable(PointerRNA *ptr)
+{
+ KeyingSet *ks= (KeyingSet *)ptr->data;
+
+ /* only editable if we're using relative paths */
+ return ((ks->flag & KEYINGSET_ABSOLUTE)==0);
+}
+
static int rna_KeyingSet_active_ksPath_editable(PointerRNA *ptr)
{
KeyingSet *ks= (KeyingSet *)ptr->data;
@@ -167,6 +322,91 @@ static void rna_KeyingSet_active_ksPath_index_range(PointerRNA *ptr, int *min, i
#else
+/* helper function for Keying Set -> keying settings */
+static void rna_def_common_keying_flags(StructRNA *srna, short reg)
+{
+ PropertyRNA *prop;
+
+ prop= RNA_def_property(srna, "insertkey_needed", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_NEEDED);
+ RNA_def_property_ui_text(prop, "Insert Keyframes - Only Needed", "Only insert keyframes where they're needed in the relevant F-Curves");
+ if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop= RNA_def_property(srna, "insertkey_visual", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_MATRIX);
+ RNA_def_property_ui_text(prop, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'");
+ if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop= RNA_def_property(srna, "insertkey_xyz_to_rgb", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_XYZ2RGB);
+ RNA_def_property_ui_text(prop, "F-Curve Colors - XYZ to RGB", "Color for newly added transformation F-Curves (Location, Rotation, Scale) and also Color is based on the transform axis");
+ if (reg) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+}
+
+/* --- */
+
+static void rna_def_keyingset_info(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ srna= RNA_def_struct(brna, "KeyingSetInfo", NULL);
+ RNA_def_struct_sdna(srna, "KeyingSetInfo");
+ RNA_def_struct_ui_text(srna, "Keying Set Info", "Callback function defines for relative Keying Sets");
+ RNA_def_struct_refine_func(srna, "rna_KeyingSetInfo_refine");
+ RNA_def_struct_register_funcs(srna, "rna_KeyingSetInfo_register", "rna_KeyingSetInfo_unregister");
+
+ /* Properties --------------------- */
+
+ RNA_define_verify_sdna(0); // not in sdna
+
+ /* Name */
+ prop= RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "name");
+ RNA_def_property_ui_text(prop, "Name", "");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+
+ prop= RNA_def_property(srna, "bl_builtin", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "builtin", 1);
+ RNA_def_property_ui_text(prop, "BuiltIn", "Keying Set type is required internally.");
+ RNA_def_property_flag(prop, PROP_REGISTER);
+
+ rna_def_common_keying_flags(srna, 1); /* '1' arg here is to indicate that we need these to be set on registering */
+
+ RNA_define_verify_sdna(1);
+
+ /* Function Callbacks ------------- */
+ /* poll */
+ func= RNA_def_function(srna, "poll", NULL);
+ RNA_def_function_ui_description(func, "Test if Keying Set can be used or not");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ RNA_def_function_return(func, RNA_def_boolean(func, "ok", 1, "", ""));
+ parm= RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ /* iterator */
+ func= RNA_def_function(srna, "iterator", NULL);
+ RNA_def_function_ui_description(func, "Call generate() on the structs which have properties to be keyframed");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm= RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm= RNA_def_pointer(func, "ks", "KeyingSet", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ /* generate */
+ func= RNA_def_function(srna, "generate", NULL);
+ RNA_def_function_ui_description(func, "Add Paths to the Keying Set to keyframe the properties of the given data");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm= RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm= RNA_def_pointer(func, "ks", "KeyingSet", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm= RNA_def_pointer(func, "data", NULL, "", ""); // "AnyType"...
+ RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR|PROP_NEVER_NULL);
+}
static void rna_def_keyingset_path(BlenderRNA *brna)
{
@@ -215,6 +455,9 @@ static void rna_def_keyingset_path(BlenderRNA *brna)
prop= RNA_def_property(srna, "entire_array", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", KSP_FLAG_WHOLE_ARRAY);
RNA_def_property_ui_text(prop, "Entire Array", "When an 'array/vector' type is chosen (Location, Rotation, Color, etc.), entire array is to be used");
+
+ /* Keyframing Settings */
+ rna_def_common_keying_flags(srna, 0);
}
static void rna_def_keyingset(BlenderRNA *brna)
@@ -230,6 +473,13 @@ static void rna_def_keyingset(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Name", "");
RNA_def_struct_name_property(srna, prop);
+ /* TypeInfo associated with Relative KeyingSet (only) */
+ prop= RNA_def_property(srna, "typeinfo_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo");
+ RNA_def_property_editable_func(prop, "rna_KeyingSet_typeinfo_name_editable");
+ RNA_def_property_ui_text(prop, "TypeInfo Name", "");
+
/* Paths */
prop= RNA_def_property(srna, "paths", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "paths", NULL);
@@ -249,28 +499,13 @@ static void rna_def_keyingset(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Active Path Index", "Current Keying Set index");
/* Flags */
- // XXX: depreceated
- prop= RNA_def_property(srna, "builtin", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYINGSET_BUILTIN);
- RNA_def_property_ui_text(prop, "Built-In", "Keying Set is a built-in to Blender");
-
prop= RNA_def_property(srna, "absolute", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYINGSET_ABSOLUTE);
RNA_def_property_ui_text(prop, "Absolute", "Keying Set defines specific paths/settings to be keyframed (i.e. is not reliant on context info)");
/* Keyframing Flags */
- prop= RNA_def_property(srna, "insertkey_needed", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_NEEDED);
- RNA_def_property_ui_text(prop, "Insert Keyframes - Only Needed", "Only insert keyframes where they're needed in the relevant F-Curves");
-
- prop= RNA_def_property(srna, "insertkey_visual", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_MATRIX);
- RNA_def_property_ui_text(prop, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'");
+ rna_def_common_keying_flags(srna, 0);
- prop= RNA_def_property(srna, "insertkey_xyz_to_rgb", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "keyingflag", INSERTKEY_XYZ2RGB);
- RNA_def_property_ui_text(prop, "F-Curve Colors - XYZ to RGB", "Color for newly added transformation F-Curves (Location, Rotation, Scale) and also Color is based on the transform axis");
/* Keying Set API */
RNA_api_keyingset(srna);
@@ -347,6 +582,7 @@ void RNA_def_animation(BlenderRNA *brna)
rna_def_keyingset(brna);
rna_def_keyingset_path(brna);
+ rna_def_keyingset_info(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_animation_api.c b/source/blender/makesrna/intern/rna_animation_api.c
index b07f147ac96..46ecc8679e7 100644
--- a/source/blender/makesrna/intern/rna_animation_api.c
+++ b/source/blender/makesrna/intern/rna_animation_api.c
@@ -41,10 +41,11 @@
#include "BKE_animsys.h"
-static void rna_KeyingSet_add_path(KeyingSet *keyingset, ReportList *reports,
+static KS_Path *rna_KeyingSet_add_path(KeyingSet *keyingset, ReportList *reports,
ID *id, char rna_path[], int array_index, int entire_array,
int grouping_method, char group_name[])
{
+ KS_Path *ksp = NULL;
short flag = 0;
/* validate flags */
@@ -53,12 +54,31 @@ static void rna_KeyingSet_add_path(KeyingSet *keyingset, ReportList *reports,
/* if data is valid, call the API function for this */
if (keyingset) {
- BKE_keyingset_add_path(keyingset, id, group_name, rna_path, array_index, flag, grouping_method);
+ ksp= BKE_keyingset_add_path(keyingset, id, group_name, rna_path, array_index, flag, grouping_method);
keyingset->active_path= BLI_countlist(&keyingset->paths);
}
else {
BKE_report(reports, RPT_ERROR, "Keying Set Path could not be added.");
}
+
+ /* return added path */
+ return ksp;
+}
+
+static void rna_KeyingSet_remove_path(KeyingSet *keyingset, ReportList *reports, KS_Path *ksp)
+{
+ /* if data is valid, call the API function for this */
+ if (keyingset && ksp) {
+ /* remove the active path from the KeyingSet */
+ BKE_keyingset_free_path(keyingset, ksp);
+
+ /* the active path number will most likely have changed */
+ // TODO: we should get more fancy and actually check if it was removed, but this will do for now
+ keyingset->active_path = 0;
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Keying Set Path could not be removed.");
+ }
}
#else
@@ -68,10 +88,13 @@ void RNA_api_keyingset(StructRNA *srna)
FunctionRNA *func;
PropertyRNA *parm;
- /* Add Destination */
+ /* Add Path */
func= RNA_def_function(srna, "add_path", "rna_KeyingSet_add_path");
- RNA_def_function_ui_description(func, "Add a new destination for the Keying Set.");
+ RNA_def_function_ui_description(func, "Add a new path for the Keying Set.");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ /* return arg */
+ parm= RNA_def_pointer(func, "ksp", "KeyingSetPath", "New Path", "Path created and added to the Keying Set");
+ RNA_def_function_return(func, parm);
/* ID-block for target */
parm= RNA_def_pointer(func, "target_id", "ID", "Target ID", "ID-Datablock for the destination.");
RNA_def_property_flag(parm, PROP_REQUIRED);
@@ -84,6 +107,14 @@ void RNA_api_keyingset(StructRNA *srna)
/* grouping */
parm=RNA_def_enum(func, "grouping_method", keyingset_path_grouping_items, KSP_GROUP_KSNAME, "Grouping Method", "Method used to define which Group-name to use.");
parm=RNA_def_string(func, "group_name", "", 64, "Group Name", "Name of Action Group to assign destination to (only if grouping mode is to use this name).");
+
+ /* Remove Path */
+ func= RNA_def_function(srna, "remove_path", "rna_KeyingSet_remove_path");
+ RNA_def_function_ui_description(func, "Remove the given path from the Keying Set.");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ /* path to remove */
+ parm= RNA_def_pointer(func, "path", "KeyingSetPath", "Path", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
}
#endif
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 5302cb1eaaf..ae310a7f59d 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -128,8 +128,6 @@ void WM_init(bContext *C, int argc, char **argv)
BLF_init(11, U.dpi);
BLF_lang_init();
- init_builtin_keyingsets(); /* editors/animation/keyframing.c */
-
/* get the default database, plus a wm */
WM_read_homefile(C, NULL);
@@ -281,7 +279,9 @@ void WM_exit(bContext *C)
// fsmenu_free();
BLF_exit();
-
+
+ ANIM_keyingset_infos_exit();
+
RE_FreeAllRender();
RE_engines_exit();