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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2010-03-16 09:18:49 +0300
committerJoshua Leung <aligorith@gmail.com>2010-03-16 09:18:49 +0300
commitea4a987fd424de77465f1a2cd95a655ccf42fd31 (patch)
treefe49fdb0e18ce012a3a366db7bed703635e0568c /source/blender/makesrna
parent604a2b1a1879c1e0ad1f637f5edc1ab12f61c31d (diff)
== Massive Keying Sets Recode ==
After a few days of wrong turns and learning the finer points of RNA-type-subclassing the hard way, this commit finally presents a refactored version of the Keying Sets system (now version 2) based on some requirements from Cessen. For a more thorough discussion of this commit, see http://sites.google.com/site/aligorith/keyingsets_2.pdf?attredirects=0&d=1 ------ The main highlight of this refactor is that relative Keying Sets have now been recoded so that Python callbacks are run to generate the Keying Set's list of paths everytime the Keying Set is used (to insert or delete keyframes), allowing complex heuristics to be used to determine whether a property gets keyframed based on the current context. These checks may include checking on selection status of related entities, or transform locks. Built-In KeyingSets have also been recoded, and moved from C and out into Python. These are now coded as Relative Keying Sets, and can to some extent serve as basis for adding new relative Keying Sets. However, these have mostly been coded in a slightly 'modular' way which may be confusing for those not so familiar with Python in general. A usable template will be added soon for more general usage. Keyframing settings (i.e. 'visual', 'needed') can now be specified on a per-path basis now, which is especially useful for Absolute Keying Sets, where control over this is often beneficial. Most of the places where Auto-Keyframing is performed have been tidied up for consistency. I'm sure quite a few issues still exist there, but these I'll clean up over the next few days.
Diffstat (limited to 'source/blender/makesrna')
-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
3 files changed, 289 insertions, 21 deletions
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