From e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2019 06:17:24 +0200 Subject: ClangFormat: apply to source, most of intern Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat --- source/blender/editors/animation/drivers.c | 1788 +++++++++++++++------------- 1 file changed, 940 insertions(+), 848 deletions(-) (limited to 'source/blender/editors/animation/drivers.c') diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index d726c25816b..d6564be9574 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -21,7 +21,6 @@ * \ingroup edanimation */ - #include #include @@ -70,212 +69,216 @@ */ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add) { - AnimData *adt; - FCurve *fcu; - - /* sanity checks */ - if (ELEM(NULL, id, rna_path)) - return NULL; - - /* init animdata if none available yet */ - adt = BKE_animdata_from_id(id); - if ((adt == NULL) && (add)) - adt = BKE_animdata_add_id(id); - if (adt == NULL) { - /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ - return NULL; - } - - /* try to find f-curve matching for this setting - * - add if not found and allowed to add one - * TODO: add auto-grouping support? how this works will need to be resolved - */ - fcu = list_find_fcurve(&adt->drivers, rna_path, array_index); - - if ((fcu == NULL) && (add)) { - /* use default settings to make a F-Curve */ - fcu = MEM_callocN(sizeof(FCurve), "FCurve"); - - fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED); - fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL; - - /* store path - make copy, and store that */ - fcu->rna_path = BLI_strdup(rna_path); - fcu->array_index = array_index; - - /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */ - if (add > 0) { - BezTriple *bezt; - size_t i; - - /* add some new driver data */ - fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); - - /* F-Modifier or Keyframes? */ - // FIXME: replace these magic numbers with defines - if (add == 2) { - /* Python API Backwards compatibility hack: - * Create FModifier so that old scripts won't break - * for now before 2.7 series -- (September 4, 2013) - */ - add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu); - } - else { - /* add 2 keyframes so that user has something to work with - * - These are configured to 0,0 and 1,1 to give a 1-1 mapping - * which can be easily tweaked from there. - */ - insert_vert_fcurve(fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST); - insert_vert_fcurve(fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST); - - /* configure this curve to extrapolate */ - for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) { - bezt->h1 = bezt->h2 = HD_VECT; - } - - fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; - calchandles_fcurve(fcu); - } - } - - /* just add F-Curve to end of driver list */ - BLI_addtail(&adt->drivers, fcu); - } - - /* return the F-Curve */ - return fcu; + AnimData *adt; + FCurve *fcu; + + /* sanity checks */ + if (ELEM(NULL, id, rna_path)) + return NULL; + + /* init animdata if none available yet */ + adt = BKE_animdata_from_id(id); + if ((adt == NULL) && (add)) + adt = BKE_animdata_add_id(id); + if (adt == NULL) { + /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ + return NULL; + } + + /* try to find f-curve matching for this setting + * - add if not found and allowed to add one + * TODO: add auto-grouping support? how this works will need to be resolved + */ + fcu = list_find_fcurve(&adt->drivers, rna_path, array_index); + + if ((fcu == NULL) && (add)) { + /* use default settings to make a F-Curve */ + fcu = MEM_callocN(sizeof(FCurve), "FCurve"); + + fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED); + fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL; + + /* store path - make copy, and store that */ + fcu->rna_path = BLI_strdup(rna_path); + fcu->array_index = array_index; + + /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */ + if (add > 0) { + BezTriple *bezt; + size_t i; + + /* add some new driver data */ + fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); + + /* F-Modifier or Keyframes? */ + // FIXME: replace these magic numbers with defines + if (add == 2) { + /* Python API Backwards compatibility hack: + * Create FModifier so that old scripts won't break + * for now before 2.7 series -- (September 4, 2013) + */ + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu); + } + else { + /* add 2 keyframes so that user has something to work with + * - These are configured to 0,0 and 1,1 to give a 1-1 mapping + * which can be easily tweaked from there. + */ + insert_vert_fcurve(fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST); + insert_vert_fcurve(fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST); + + /* configure this curve to extrapolate */ + for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) { + bezt->h1 = bezt->h2 = HD_VECT; + } + + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + calchandles_fcurve(fcu); + } + } + + /* just add F-Curve to end of driver list */ + BLI_addtail(&adt->drivers, fcu); + } + + /* return the F-Curve */ + return fcu; } /* ************************************************** */ /* Driver Management API */ /* Helper for ANIM_add_driver_with_target - Adds the actual driver */ -static int add_driver_with_target( - ReportList *UNUSED(reports), - ID *dst_id, const char dst_path[], int dst_index, - ID *src_id, const char src_path[], int src_index, - PointerRNA *dst_ptr, PropertyRNA *dst_prop, - PointerRNA *src_ptr, PropertyRNA *src_prop, - short flag, int driver_type) +static int add_driver_with_target(ReportList *UNUSED(reports), + ID *dst_id, + const char dst_path[], + int dst_index, + ID *src_id, + const char src_path[], + int src_index, + PointerRNA *dst_ptr, + PropertyRNA *dst_prop, + PointerRNA *src_ptr, + PropertyRNA *src_prop, + short flag, + int driver_type) { - FCurve *fcu; - short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1; - const char *prop_name = RNA_property_identifier(src_prop); - - /* Create F-Curve with Driver */ - fcu = verify_driver_fcurve(dst_id, dst_path, dst_index, add_mode); - - if (fcu && fcu->driver) { - ChannelDriver *driver = fcu->driver; - DriverVar *dvar; - - /* Set the type of the driver */ - driver->type = driver_type; - - /* Set driver expression, so that the driver works out of the box - * - * The following checks define a bit of "autodetection magic" we use - * to ensure that the drivers will behave as expected out of the box - * when faced with properties with different units. - */ - /* XXX: if we have N-1 mapping, should we include all those in the expression? */ - if ((RNA_property_unit(dst_prop) == PROP_UNIT_ROTATION) && - (RNA_property_unit(src_prop) != PROP_UNIT_ROTATION)) - { - /* Rotation Destination: normal -> radians, so convert src to radians - * (However, if both input and output is a rotation, don't apply such corrections) - */ - BLI_strncpy(driver->expression, "radians(var)", sizeof(driver->expression)); - } - else if ((RNA_property_unit(src_prop) == PROP_UNIT_ROTATION) && - (RNA_property_unit(dst_prop) != PROP_UNIT_ROTATION)) - { - /* Rotation Source: radians -> normal, so convert src to degrees - * (However, if both input and output is a rotation, don't apply such corrections) - */ - BLI_strncpy(driver->expression, "degrees(var)", sizeof(driver->expression)); - } - else { - /* Just a normal property without any unit problems */ - BLI_strncpy(driver->expression, "var", sizeof(driver->expression)); - } - - /* Create a driver variable for the target - * - For transform properties, we want to automatically use "transform channel" instead - * (The only issue is with quat rotations vs euler channels...) - * - To avoid problems with transform properties depending on the final transform that they - * control (thus creating pseudo-cycles - see T48734), we don't use transform channels - * when both the source and destinations are in same places. - */ - dvar = driver_add_new_variable(driver); - - if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) && - (STREQ(prop_name, "location") || STREQ(prop_name, "scale") || STRPREFIX(prop_name, "rotation_")) && - (src_ptr->data != dst_ptr->data)) - { - /* Transform Channel */ - DriverTarget *dtar; - - driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); - dtar = &dvar->targets[0]; - - /* Bone or Object target? */ - dtar->id = src_id; - dtar->idtype = GS(src_id->name); - - if (src_ptr->type == &RNA_PoseBone) { - RNA_string_get(src_ptr, "name", dtar->pchan_name); - } - - /* Transform channel depends on type */ - if (STREQ(prop_name, "location")) { - if (src_index == 2) - dtar->transChan = DTAR_TRANSCHAN_LOCZ; - else if (src_index == 1) - dtar->transChan = DTAR_TRANSCHAN_LOCY; - else - dtar->transChan = DTAR_TRANSCHAN_LOCX; - } - else if (STREQ(prop_name, "scale")) { - if (src_index == 2) - dtar->transChan = DTAR_TRANSCHAN_SCALEZ; - else if (src_index == 1) - dtar->transChan = DTAR_TRANSCHAN_SCALEY; - else - dtar->transChan = DTAR_TRANSCHAN_SCALEX; - } - else { - /* XXX: With quaternions and axis-angle, this mapping might not be correct... - * But since those have 4 elements instead, there's not much we can do - */ - if (src_index == 2) - dtar->transChan = DTAR_TRANSCHAN_ROTZ; - else if (src_index == 1) - dtar->transChan = DTAR_TRANSCHAN_ROTY; - else - dtar->transChan = DTAR_TRANSCHAN_ROTX; - } - } - else { - /* Single RNA Property */ - DriverTarget *dtar = &dvar->targets[0]; - - /* ID is as-is */ - dtar->id = src_id; - dtar->idtype = GS(src_id->name); - - /* Need to make a copy of the path (or build one with array index built in) */ - if (RNA_property_array_check(src_prop)) { - dtar->rna_path = BLI_sprintfN("%s[%d]", src_path, src_index); - } - else { - dtar->rna_path = BLI_strdup(src_path); - } - } - } - - /* set the done status */ - return (fcu != NULL); + FCurve *fcu; + short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1; + const char *prop_name = RNA_property_identifier(src_prop); + + /* Create F-Curve with Driver */ + fcu = verify_driver_fcurve(dst_id, dst_path, dst_index, add_mode); + + if (fcu && fcu->driver) { + ChannelDriver *driver = fcu->driver; + DriverVar *dvar; + + /* Set the type of the driver */ + driver->type = driver_type; + + /* Set driver expression, so that the driver works out of the box + * + * The following checks define a bit of "autodetection magic" we use + * to ensure that the drivers will behave as expected out of the box + * when faced with properties with different units. + */ + /* XXX: if we have N-1 mapping, should we include all those in the expression? */ + if ((RNA_property_unit(dst_prop) == PROP_UNIT_ROTATION) && + (RNA_property_unit(src_prop) != PROP_UNIT_ROTATION)) { + /* Rotation Destination: normal -> radians, so convert src to radians + * (However, if both input and output is a rotation, don't apply such corrections) + */ + BLI_strncpy(driver->expression, "radians(var)", sizeof(driver->expression)); + } + else if ((RNA_property_unit(src_prop) == PROP_UNIT_ROTATION) && + (RNA_property_unit(dst_prop) != PROP_UNIT_ROTATION)) { + /* Rotation Source: radians -> normal, so convert src to degrees + * (However, if both input and output is a rotation, don't apply such corrections) + */ + BLI_strncpy(driver->expression, "degrees(var)", sizeof(driver->expression)); + } + else { + /* Just a normal property without any unit problems */ + BLI_strncpy(driver->expression, "var", sizeof(driver->expression)); + } + + /* Create a driver variable for the target + * - For transform properties, we want to automatically use "transform channel" instead + * (The only issue is with quat rotations vs euler channels...) + * - To avoid problems with transform properties depending on the final transform that they + * control (thus creating pseudo-cycles - see T48734), we don't use transform channels + * when both the source and destinations are in same places. + */ + dvar = driver_add_new_variable(driver); + + if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) && + (STREQ(prop_name, "location") || STREQ(prop_name, "scale") || + STRPREFIX(prop_name, "rotation_")) && + (src_ptr->data != dst_ptr->data)) { + /* Transform Channel */ + DriverTarget *dtar; + + driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); + dtar = &dvar->targets[0]; + + /* Bone or Object target? */ + dtar->id = src_id; + dtar->idtype = GS(src_id->name); + + if (src_ptr->type == &RNA_PoseBone) { + RNA_string_get(src_ptr, "name", dtar->pchan_name); + } + + /* Transform channel depends on type */ + if (STREQ(prop_name, "location")) { + if (src_index == 2) + dtar->transChan = DTAR_TRANSCHAN_LOCZ; + else if (src_index == 1) + dtar->transChan = DTAR_TRANSCHAN_LOCY; + else + dtar->transChan = DTAR_TRANSCHAN_LOCX; + } + else if (STREQ(prop_name, "scale")) { + if (src_index == 2) + dtar->transChan = DTAR_TRANSCHAN_SCALEZ; + else if (src_index == 1) + dtar->transChan = DTAR_TRANSCHAN_SCALEY; + else + dtar->transChan = DTAR_TRANSCHAN_SCALEX; + } + else { + /* XXX: With quaternions and axis-angle, this mapping might not be correct... + * But since those have 4 elements instead, there's not much we can do + */ + if (src_index == 2) + dtar->transChan = DTAR_TRANSCHAN_ROTZ; + else if (src_index == 1) + dtar->transChan = DTAR_TRANSCHAN_ROTY; + else + dtar->transChan = DTAR_TRANSCHAN_ROTX; + } + } + else { + /* Single RNA Property */ + DriverTarget *dtar = &dvar->targets[0]; + + /* ID is as-is */ + dtar->id = src_id; + dtar->idtype = GS(src_id->name); + + /* Need to make a copy of the path (or build one with array index built in) */ + if (RNA_property_array_check(src_prop)) { + dtar->rna_path = BLI_sprintfN("%s[%d]", src_path, src_index); + } + else { + dtar->rna_path = BLI_strdup(src_path); + } + } + } + + /* set the done status */ + return (fcu != NULL); } /* Main Driver Management API calls: @@ -289,75 +292,118 @@ static int add_driver_with_target( * - driver_type: eDriver_Types * - mapping_type: eCreateDriver_MappingTypes */ -int ANIM_add_driver_with_target( - ReportList *reports, - ID *dst_id, const char dst_path[], int dst_index, - ID *src_id, const char src_path[], int src_index, - short flag, int driver_type, short mapping_type) +int ANIM_add_driver_with_target(ReportList *reports, + ID *dst_id, + const char dst_path[], + int dst_index, + ID *src_id, + const char src_path[], + int src_index, + short flag, + int driver_type, + short mapping_type) { - PointerRNA id_ptr, ptr; - PropertyRNA *prop; - - PointerRNA id_ptr2, ptr2; - PropertyRNA *prop2; - int done_tot = 0; - - /* validate pointers first - exit if failure */ - RNA_id_pointer_create(dst_id, &id_ptr); - if (RNA_path_resolve_property(&id_ptr, dst_path, &ptr, &prop) == false) { - BKE_reportf(reports, RPT_ERROR, - "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)", - dst_id->name, dst_path); - return 0; - } - - RNA_id_pointer_create(src_id, &id_ptr2); - if ((RNA_path_resolve_property(&id_ptr2, src_path, &ptr2, &prop2) == false) || - (mapping_type == CREATEDRIVER_MAPPING_NONE)) - { - /* No target - So, fall back to default method for adding a "simple" driver normally */ - return ANIM_add_driver(reports, dst_id, dst_path, dst_index, flag | CREATEDRIVER_WITH_DEFAULT_DVAR, driver_type); - } - - /* handle curve-property mappings based on mapping_type */ - switch (mapping_type) { - case CREATEDRIVER_MAPPING_N_N: /* N-N - Try to match as much as possible, - * then use the first one */ - { - /* Use the shorter of the two (to avoid out of bounds access) */ - int dst_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1; - int src_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr2, prop2) : 1; - - int len = MIN2(dst_len, src_len); - int i; - - for (i = 0; i < len; i++) { - done_tot += add_driver_with_target(reports, dst_id, dst_path, i, src_id, src_path, i, &ptr, prop, &ptr2, prop2, flag, driver_type); - } - break; - } - - case CREATEDRIVER_MAPPING_1_N: /* 1-N - Specified target index for all */ - default: - { - int len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1; - int i; - - for (i = 0; i < len; i++) { - done_tot += add_driver_with_target(reports, dst_id, dst_path, i, src_id, src_path, src_index, &ptr, prop, &ptr2, prop2, flag, driver_type); - } - break; - } - - case CREATEDRIVER_MAPPING_1_1: /* 1-1 - Use the specified index (unless -1) */ - { - done_tot = add_driver_with_target(reports, dst_id, dst_path, dst_index, src_id, src_path, src_index, &ptr, prop, &ptr2, prop2, flag, driver_type); - break; - } - } - - /* done */ - return done_tot; + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + + PointerRNA id_ptr2, ptr2; + PropertyRNA *prop2; + int done_tot = 0; + + /* validate pointers first - exit if failure */ + RNA_id_pointer_create(dst_id, &id_ptr); + if (RNA_path_resolve_property(&id_ptr, dst_path, &ptr, &prop) == false) { + BKE_reportf( + reports, + RPT_ERROR, + "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)", + dst_id->name, + dst_path); + return 0; + } + + RNA_id_pointer_create(src_id, &id_ptr2); + if ((RNA_path_resolve_property(&id_ptr2, src_path, &ptr2, &prop2) == false) || + (mapping_type == CREATEDRIVER_MAPPING_NONE)) { + /* No target - So, fall back to default method for adding a "simple" driver normally */ + return ANIM_add_driver( + reports, dst_id, dst_path, dst_index, flag | CREATEDRIVER_WITH_DEFAULT_DVAR, driver_type); + } + + /* handle curve-property mappings based on mapping_type */ + switch (mapping_type) { + case CREATEDRIVER_MAPPING_N_N: /* N-N - Try to match as much as possible, + * then use the first one */ + { + /* Use the shorter of the two (to avoid out of bounds access) */ + int dst_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1; + int src_len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr2, prop2) : 1; + + int len = MIN2(dst_len, src_len); + int i; + + for (i = 0; i < len; i++) { + done_tot += add_driver_with_target(reports, + dst_id, + dst_path, + i, + src_id, + src_path, + i, + &ptr, + prop, + &ptr2, + prop2, + flag, + driver_type); + } + break; + } + + case CREATEDRIVER_MAPPING_1_N: /* 1-N - Specified target index for all */ + default: { + int len = (RNA_property_array_check(prop)) ? RNA_property_array_length(&ptr, prop) : 1; + int i; + + for (i = 0; i < len; i++) { + done_tot += add_driver_with_target(reports, + dst_id, + dst_path, + i, + src_id, + src_path, + src_index, + &ptr, + prop, + &ptr2, + prop2, + flag, + driver_type); + } + break; + } + + case CREATEDRIVER_MAPPING_1_1: /* 1-1 - Use the specified index (unless -1) */ + { + done_tot = add_driver_with_target(reports, + dst_id, + dst_path, + dst_index, + src_id, + src_path, + src_index, + &ptr, + prop, + &ptr2, + prop2, + flag, + driver_type); + break; + } + } + + /* done */ + return done_tot; } /* --------------------------------- */ @@ -365,155 +411,169 @@ int ANIM_add_driver_with_target( /* Main Driver Management API calls: * Add a new driver for the specified property on the given ID block */ -int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type) +int ANIM_add_driver( + ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type) { - PointerRNA id_ptr, ptr; - PropertyRNA *prop; - FCurve *fcu; - int array_index_max; - int done_tot = 0; - - /* validate pointer first - exit if failure */ - RNA_id_pointer_create(id, &id_ptr); - if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) { - BKE_reportf(reports, RPT_ERROR, - "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)", - id->name, rna_path); - return 0; - } - - /* key entire array convenience method */ - if (array_index == -1) { - array_index_max = RNA_property_array_length(&ptr, prop); - array_index = 0; - } - else - array_index_max = array_index; - - /* maximum index should be greater than the start index */ - if (array_index == array_index_max) - array_index_max += 1; - - /* will only loop once unless the array index was -1 */ - for (; array_index < array_index_max; array_index++) { - short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1; - - /* create F-Curve with Driver */ - fcu = verify_driver_fcurve(id, rna_path, array_index, add_mode); - - if (fcu && fcu->driver) { - ChannelDriver *driver = fcu->driver; - - /* set the type of the driver */ - driver->type = type; - - /* Creating drivers for buttons will create the driver(s) with type - * "scripted expression" so that their values won't be lost immediately, - * so here we copy those values over to the driver's expression - * - * If the "default dvar" option (for easier UI setup of drivers) is provided, - * include "var" in the expressions too, so that the user doesn't have to edit - * it to get something to happen. It should be fine to just add it to the default - * value, so that we get both in the expression, even if it's a bit more confusing - * that way... - */ - if (type == DRIVER_TYPE_PYTHON) { - PropertyType proptype = RNA_property_type(prop); - int array = RNA_property_array_length(&ptr, prop); - const char *dvar_prefix = (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) ? "var + " : ""; - char *expression = driver->expression; - int val, maxlen = sizeof(driver->expression); - float fval; - - if (proptype == PROP_BOOLEAN) { - if (!array) val = RNA_property_boolean_get(&ptr, prop); - else val = RNA_property_boolean_get_index(&ptr, prop, array_index); - - BLI_snprintf(expression, maxlen, "%s%s", dvar_prefix, (val) ? "True" : "False"); - } - else if (proptype == PROP_INT) { - if (!array) val = RNA_property_int_get(&ptr, prop); - else val = RNA_property_int_get_index(&ptr, prop, array_index); - - BLI_snprintf(expression, maxlen, "%s%d", dvar_prefix, val); - } - else if (proptype == PROP_FLOAT) { - if (!array) fval = RNA_property_float_get(&ptr, prop); - else fval = RNA_property_float_get_index(&ptr, prop, array_index); - - BLI_snprintf(expression, maxlen, "%s%.3f", dvar_prefix, fval); - BLI_str_rstrip_float_zero(expression, '\0'); - } - else if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { - BLI_strncpy(expression, "var", maxlen); - } - } - - /* for easier setup of drivers from UI, a driver variable should be - * added if flag is set (UI calls only) - */ - if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { - /* assume that users will mostly want this to be of type "Transform Channel" too, - * since this allows the easiest setting up of common rig components - */ - DriverVar *dvar = driver_add_new_variable(driver); - driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); - } - } - - /* set the done status */ - done_tot += (fcu != NULL); - } - - /* done */ - return done_tot; + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + FCurve *fcu; + int array_index_max; + int done_tot = 0; + + /* validate pointer first - exit if failure */ + RNA_id_pointer_create(id, &id_ptr); + if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) { + BKE_reportf( + reports, + RPT_ERROR, + "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)", + id->name, + rna_path); + return 0; + } + + /* key entire array convenience method */ + if (array_index == -1) { + array_index_max = RNA_property_array_length(&ptr, prop); + array_index = 0; + } + else + array_index_max = array_index; + + /* maximum index should be greater than the start index */ + if (array_index == array_index_max) + array_index_max += 1; + + /* will only loop once unless the array index was -1 */ + for (; array_index < array_index_max; array_index++) { + short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1; + + /* create F-Curve with Driver */ + fcu = verify_driver_fcurve(id, rna_path, array_index, add_mode); + + if (fcu && fcu->driver) { + ChannelDriver *driver = fcu->driver; + + /* set the type of the driver */ + driver->type = type; + + /* Creating drivers for buttons will create the driver(s) with type + * "scripted expression" so that their values won't be lost immediately, + * so here we copy those values over to the driver's expression + * + * If the "default dvar" option (for easier UI setup of drivers) is provided, + * include "var" in the expressions too, so that the user doesn't have to edit + * it to get something to happen. It should be fine to just add it to the default + * value, so that we get both in the expression, even if it's a bit more confusing + * that way... + */ + if (type == DRIVER_TYPE_PYTHON) { + PropertyType proptype = RNA_property_type(prop); + int array = RNA_property_array_length(&ptr, prop); + const char *dvar_prefix = (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) ? "var + " : ""; + char *expression = driver->expression; + int val, maxlen = sizeof(driver->expression); + float fval; + + if (proptype == PROP_BOOLEAN) { + if (!array) + val = RNA_property_boolean_get(&ptr, prop); + else + val = RNA_property_boolean_get_index(&ptr, prop, array_index); + + BLI_snprintf(expression, maxlen, "%s%s", dvar_prefix, (val) ? "True" : "False"); + } + else if (proptype == PROP_INT) { + if (!array) + val = RNA_property_int_get(&ptr, prop); + else + val = RNA_property_int_get_index(&ptr, prop, array_index); + + BLI_snprintf(expression, maxlen, "%s%d", dvar_prefix, val); + } + else if (proptype == PROP_FLOAT) { + if (!array) + fval = RNA_property_float_get(&ptr, prop); + else + fval = RNA_property_float_get_index(&ptr, prop, array_index); + + BLI_snprintf(expression, maxlen, "%s%.3f", dvar_prefix, fval); + BLI_str_rstrip_float_zero(expression, '\0'); + } + else if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { + BLI_strncpy(expression, "var", maxlen); + } + } + + /* for easier setup of drivers from UI, a driver variable should be + * added if flag is set (UI calls only) + */ + if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) { + /* assume that users will mostly want this to be of type "Transform Channel" too, + * since this allows the easiest setting up of common rig components + */ + DriverVar *dvar = driver_add_new_variable(driver); + driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN); + } + } + + /* set the done status */ + done_tot += (fcu != NULL); + } + + /* done */ + return done_tot; } /* Main Driver Management API calls: * Remove the driver for the specified property on the given ID block (if available) */ -bool ANIM_remove_driver(ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag)) +bool ANIM_remove_driver(ReportList *UNUSED(reports), + ID *id, + const char rna_path[], + int array_index, + short UNUSED(flag)) { - AnimData *adt; - FCurve *fcu; - bool success = false; - - /* we don't check the validity of the path here yet, but it should be ok... */ - adt = BKE_animdata_from_id(id); - - if (adt) { - if (array_index == -1) { - /* step through all drivers, removing all of those with the same base path */ - FCurve *fcu_iter = adt->drivers.first; - - while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) { - /* store the next fcurve for looping */ - fcu_iter = fcu->next; - - /* remove F-Curve from driver stack, then free it */ - BLI_remlink(&adt->drivers, fcu); - free_fcurve(fcu); - - /* done successfully */ - success = true; - } - } - else { - /* find the matching driver and remove it only - * Note: here is one of the places where we don't want new F-Curve + Driver added! - * so 'add' var must be 0 - */ - fcu = verify_driver_fcurve(id, rna_path, array_index, 0); - if (fcu) { - BLI_remlink(&adt->drivers, fcu); - free_fcurve(fcu); - - success = true; - } - } - } - - return success; + AnimData *adt; + FCurve *fcu; + bool success = false; + + /* we don't check the validity of the path here yet, but it should be ok... */ + adt = BKE_animdata_from_id(id); + + if (adt) { + if (array_index == -1) { + /* step through all drivers, removing all of those with the same base path */ + FCurve *fcu_iter = adt->drivers.first; + + while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) { + /* store the next fcurve for looping */ + fcu_iter = fcu->next; + + /* remove F-Curve from driver stack, then free it */ + BLI_remlink(&adt->drivers, fcu); + free_fcurve(fcu); + + /* done successfully */ + success = true; + } + } + else { + /* find the matching driver and remove it only + * Note: here is one of the places where we don't want new F-Curve + Driver added! + * so 'add' var must be 0 + */ + fcu = verify_driver_fcurve(id, rna_path, array_index, 0); + if (fcu) { + BLI_remlink(&adt->drivers, fcu); + free_fcurve(fcu); + + success = true; + } + } + } + + return success; } /* ************************************************** */ @@ -525,16 +585,16 @@ static FCurve *channeldriver_copypaste_buf = NULL; /* This function frees any MEM_calloc'ed copy/paste buffer data */ void ANIM_drivers_copybuf_free(void) { - /* free the buffer F-Curve if it exists, as if it were just another F-Curve */ - if (channeldriver_copypaste_buf) - free_fcurve(channeldriver_copypaste_buf); - channeldriver_copypaste_buf = NULL; + /* free the buffer F-Curve if it exists, as if it were just another F-Curve */ + if (channeldriver_copypaste_buf) + free_fcurve(channeldriver_copypaste_buf); + channeldriver_copypaste_buf = NULL; } /* Checks if there is a driver in the copy/paste buffer */ bool ANIM_driver_can_paste(void) { - return (channeldriver_copypaste_buf != NULL); + return (channeldriver_copypaste_buf != NULL); } /* ------------------- */ @@ -542,98 +602,106 @@ bool ANIM_driver_can_paste(void) /* Main Driver Management API calls: * Make a copy of the driver for the specified property on the given ID block */ -bool ANIM_copy_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag)) +bool ANIM_copy_driver( + ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag)) { - PointerRNA id_ptr, ptr; - PropertyRNA *prop; - FCurve *fcu; - - /* validate pointer first - exit if failure */ - RNA_id_pointer_create(id, &id_ptr); - if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) { - BKE_reportf(reports, RPT_ERROR, - "Could not find driver to copy, as RNA path is invalid for the given ID (ID = %s, path = %s)", - id->name, rna_path); - return 0; - } - - /* try to get F-Curve with Driver */ - fcu = verify_driver_fcurve(id, rna_path, array_index, 0); - - /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */ - ANIM_drivers_copybuf_free(); - - /* copy this to the copy/paste buf if it exists */ - if (fcu && fcu->driver) { - /* make copies of some info such as the rna_path, then clear this info from the F-Curve temporarily - * so that we don't end up wasting memory storing the path which won't get used ever... - */ - char *tmp_path = fcu->rna_path; - fcu->rna_path = NULL; - - /* make a copy of the F-Curve with */ - channeldriver_copypaste_buf = copy_fcurve(fcu); - - /* restore the path */ - fcu->rna_path = tmp_path; - - /* copied... */ - return 1; - } - - /* done */ - return 0; + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + FCurve *fcu; + + /* validate pointer first - exit if failure */ + RNA_id_pointer_create(id, &id_ptr); + if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) { + BKE_reportf(reports, + RPT_ERROR, + "Could not find driver to copy, as RNA path is invalid for the given ID (ID = %s, " + "path = %s)", + id->name, + rna_path); + return 0; + } + + /* try to get F-Curve with Driver */ + fcu = verify_driver_fcurve(id, rna_path, array_index, 0); + + /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */ + ANIM_drivers_copybuf_free(); + + /* copy this to the copy/paste buf if it exists */ + if (fcu && fcu->driver) { + /* make copies of some info such as the rna_path, then clear this info from the F-Curve temporarily + * so that we don't end up wasting memory storing the path which won't get used ever... + */ + char *tmp_path = fcu->rna_path; + fcu->rna_path = NULL; + + /* make a copy of the F-Curve with */ + channeldriver_copypaste_buf = copy_fcurve(fcu); + + /* restore the path */ + fcu->rna_path = tmp_path; + + /* copied... */ + return 1; + } + + /* done */ + return 0; } /* Main Driver Management API calls: * Add a new driver for the specified property on the given ID block or replace an existing one * with the driver + driver-curve data from the buffer */ -bool ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag)) +bool ANIM_paste_driver( + ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag)) { - PointerRNA id_ptr, ptr; - PropertyRNA *prop; - FCurve *fcu; - - /* validate pointer first - exit if failure */ - RNA_id_pointer_create(id, &id_ptr); - if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) { - BKE_reportf(reports, RPT_ERROR, - "Could not paste driver, as RNA path is invalid for the given ID (ID = %s, path = %s)", - id->name, rna_path); - return 0; - } - - /* if the buffer is empty, cannot paste... */ - if (channeldriver_copypaste_buf == NULL) { - BKE_report(reports, RPT_ERROR, "Paste driver: no driver to paste"); - return 0; - } - - /* create Driver F-Curve, but without data which will be copied across... */ - fcu = verify_driver_fcurve(id, rna_path, array_index, -1); - - if (fcu) { - /* copy across the curve data from the buffer curve - * NOTE: this step needs care to not miss new settings - */ - /* keyframes/samples */ - fcu->bezt = MEM_dupallocN(channeldriver_copypaste_buf->bezt); - fcu->fpt = MEM_dupallocN(channeldriver_copypaste_buf->fpt); - fcu->totvert = channeldriver_copypaste_buf->totvert; - - /* modifiers */ - copy_fmodifiers(&fcu->modifiers, &channeldriver_copypaste_buf->modifiers); - - /* extrapolation mode */ - fcu->extend = channeldriver_copypaste_buf->extend; - - /* the 'juicy' stuff - the driver */ - fcu->driver = fcurve_copy_driver(channeldriver_copypaste_buf->driver); - } - - /* done */ - return (fcu != NULL); + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + FCurve *fcu; + + /* validate pointer first - exit if failure */ + RNA_id_pointer_create(id, &id_ptr); + if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) { + BKE_reportf( + reports, + RPT_ERROR, + "Could not paste driver, as RNA path is invalid for the given ID (ID = %s, path = %s)", + id->name, + rna_path); + return 0; + } + + /* if the buffer is empty, cannot paste... */ + if (channeldriver_copypaste_buf == NULL) { + BKE_report(reports, RPT_ERROR, "Paste driver: no driver to paste"); + return 0; + } + + /* create Driver F-Curve, but without data which will be copied across... */ + fcu = verify_driver_fcurve(id, rna_path, array_index, -1); + + if (fcu) { + /* copy across the curve data from the buffer curve + * NOTE: this step needs care to not miss new settings + */ + /* keyframes/samples */ + fcu->bezt = MEM_dupallocN(channeldriver_copypaste_buf->bezt); + fcu->fpt = MEM_dupallocN(channeldriver_copypaste_buf->fpt); + fcu->totvert = channeldriver_copypaste_buf->totvert; + + /* modifiers */ + copy_fmodifiers(&fcu->modifiers, &channeldriver_copypaste_buf->modifiers); + + /* extrapolation mode */ + fcu->extend = channeldriver_copypaste_buf->extend; + + /* the 'juicy' stuff - the driver */ + fcu->driver = fcurve_copy_driver(channeldriver_copypaste_buf->driver); + } + + /* done */ + return (fcu != NULL); } /* ************************************************** */ @@ -645,24 +713,24 @@ static ListBase driver_vars_copybuf = {NULL, NULL}; /* This function frees any MEM_calloc'ed copy/paste buffer data */ void ANIM_driver_vars_copybuf_free(void) { - /* Free the driver variables kept in the buffer */ - if (driver_vars_copybuf.first) { - DriverVar *dvar, *dvarn; - - /* Free variables (and any data they use) */ - for (dvar = driver_vars_copybuf.first; dvar; dvar = dvarn) { - dvarn = dvar->next; - driver_free_variable(&driver_vars_copybuf, dvar); - } - } - - BLI_listbase_clear(&driver_vars_copybuf); + /* Free the driver variables kept in the buffer */ + if (driver_vars_copybuf.first) { + DriverVar *dvar, *dvarn; + + /* Free variables (and any data they use) */ + for (dvar = driver_vars_copybuf.first; dvar; dvar = dvarn) { + dvarn = dvar->next; + driver_free_variable(&driver_vars_copybuf, dvar); + } + } + + BLI_listbase_clear(&driver_vars_copybuf); } /* Checks if there are driver variables in the copy/paste buffer */ bool ANIM_driver_vars_can_paste(void) { - return (BLI_listbase_is_empty(&driver_vars_copybuf) == false); + return (BLI_listbase_is_empty(&driver_vars_copybuf) == false); } /* -------------------------------------------------- */ @@ -670,78 +738,78 @@ bool ANIM_driver_vars_can_paste(void) /* Copy the given driver's variables to the buffer */ bool ANIM_driver_vars_copy(ReportList *reports, FCurve *fcu) { - /* sanity checks */ - if (ELEM(NULL, fcu, fcu->driver)) { - BKE_report(reports, RPT_ERROR, "No driver to copy variables from"); - return false; - } + /* sanity checks */ + if (ELEM(NULL, fcu, fcu->driver)) { + BKE_report(reports, RPT_ERROR, "No driver to copy variables from"); + return false; + } - if (BLI_listbase_is_empty(&fcu->driver->variables)) { - BKE_report(reports, RPT_ERROR, "Driver has no variables to copy"); - return false; - } + if (BLI_listbase_is_empty(&fcu->driver->variables)) { + BKE_report(reports, RPT_ERROR, "Driver has no variables to copy"); + return false; + } - /* clear buffer */ - ANIM_driver_vars_copybuf_free(); + /* clear buffer */ + ANIM_driver_vars_copybuf_free(); - /* copy over the variables */ - driver_variables_copy(&driver_vars_copybuf, &fcu->driver->variables); + /* copy over the variables */ + driver_variables_copy(&driver_vars_copybuf, &fcu->driver->variables); - return (BLI_listbase_is_empty(&driver_vars_copybuf) == false); + return (BLI_listbase_is_empty(&driver_vars_copybuf) == false); } /* Paste the variables in the buffer to the given FCurve */ bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace) { - ChannelDriver *driver = (fcu) ? fcu->driver : NULL; - ListBase tmp_list = {NULL, NULL}; - - /* sanity checks */ - if (BLI_listbase_is_empty(&driver_vars_copybuf)) { - BKE_report(reports, RPT_ERROR, "No driver variables in clipboard to paste"); - return false; - } - - if (ELEM(NULL, fcu, fcu->driver)) { - BKE_report(reports, RPT_ERROR, "Cannot paste driver variables without a driver"); - return false; - } - - /* 1) Make a new copy of the variables in the buffer - these will get pasted later... */ - driver_variables_copy(&tmp_list, &driver_vars_copybuf); - - /* 2) Prepare destination array */ - if (replace) { - DriverVar *dvar, *dvarn; - - /* Free all existing vars first - We aren't retaining anything */ - for (dvar = driver->variables.first; dvar; dvar = dvarn) { - dvarn = dvar->next; - driver_free_variable_ex(driver, dvar); - } - - BLI_listbase_clear(&driver->variables); - } - - /* 3) Add new vars */ - if (driver->variables.last) { - DriverVar *last = driver->variables.last; - DriverVar *first = tmp_list.first; - - last->next = first; - first->prev = last; - - driver->variables.last = tmp_list.last; - } - else { - driver->variables.first = tmp_list.first; - driver->variables.last = tmp_list.last; - } - - /* since driver variables are cached, the expression needs re-compiling too */ - BKE_driver_invalidate_expression(driver, false, true); - - return true; + ChannelDriver *driver = (fcu) ? fcu->driver : NULL; + ListBase tmp_list = {NULL, NULL}; + + /* sanity checks */ + if (BLI_listbase_is_empty(&driver_vars_copybuf)) { + BKE_report(reports, RPT_ERROR, "No driver variables in clipboard to paste"); + return false; + } + + if (ELEM(NULL, fcu, fcu->driver)) { + BKE_report(reports, RPT_ERROR, "Cannot paste driver variables without a driver"); + return false; + } + + /* 1) Make a new copy of the variables in the buffer - these will get pasted later... */ + driver_variables_copy(&tmp_list, &driver_vars_copybuf); + + /* 2) Prepare destination array */ + if (replace) { + DriverVar *dvar, *dvarn; + + /* Free all existing vars first - We aren't retaining anything */ + for (dvar = driver->variables.first; dvar; dvar = dvarn) { + dvarn = dvar->next; + driver_free_variable_ex(driver, dvar); + } + + BLI_listbase_clear(&driver->variables); + } + + /* 3) Add new vars */ + if (driver->variables.last) { + DriverVar *last = driver->variables.last; + DriverVar *first = tmp_list.first; + + last->next = first; + first->prev = last; + + driver->variables.last = tmp_list.last; + } + else { + driver->variables.first = tmp_list.first; + driver->variables.last = tmp_list.last; + } + + /* since driver variables are cached, the expression needs re-compiling too */ + BKE_driver_invalidate_expression(driver, false, true); + + return true; } /* ************************************************** */ @@ -753,397 +821,421 @@ bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace) /* NOTE: Used by ANIM_OT_driver_button_add and UI_OT_eyedropper_driver */ // XXX: These names need reviewing EnumPropertyItem prop_driver_create_mapping_types[] = { - {CREATEDRIVER_MAPPING_1_N, "SINGLE_MANY", 0, "All from Target", - "Drive all components of this property using the target picked"}, - {CREATEDRIVER_MAPPING_1_1, "DIRECT", 0, "Single from Target", - "Drive this component of this property using the target picked"}, - - {CREATEDRIVER_MAPPING_N_N, "MATCH", ICON_COLOR, "Match Indices", - "Create drivers for each pair of corresponding elements"}, - - {CREATEDRIVER_MAPPING_NONE_ALL, "NONE_ALL", ICON_HAND, "Manually Create Later", - "Create drivers for all properties without assigning any targets yet"}, - {CREATEDRIVER_MAPPING_NONE, "NONE_SINGLE", 0, "Manually Create Later (Single)", - "Create driver for this property only and without assigning any targets yet"}, - {0, NULL, 0, NULL, NULL}, + {CREATEDRIVER_MAPPING_1_N, + "SINGLE_MANY", + 0, + "All from Target", + "Drive all components of this property using the target picked"}, + {CREATEDRIVER_MAPPING_1_1, + "DIRECT", + 0, + "Single from Target", + "Drive this component of this property using the target picked"}, + + {CREATEDRIVER_MAPPING_N_N, + "MATCH", + ICON_COLOR, + "Match Indices", + "Create drivers for each pair of corresponding elements"}, + + {CREATEDRIVER_MAPPING_NONE_ALL, + "NONE_ALL", + ICON_HAND, + "Manually Create Later", + "Create drivers for all properties without assigning any targets yet"}, + {CREATEDRIVER_MAPPING_NONE, + "NONE_SINGLE", + 0, + "Manually Create Later (Single)", + "Create driver for this property only and without assigning any targets yet"}, + {0, NULL, 0, NULL, NULL}, }; /* Filtering callback for driver mapping types enum */ -static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, PointerRNA *UNUSED(owner_ptr), PropertyRNA *UNUSED(owner_prop), bool *r_free) +static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C, + PointerRNA *UNUSED(owner_ptr), + PropertyRNA *UNUSED(owner_prop), + bool *r_free) { - EnumPropertyItem *input = prop_driver_create_mapping_types; - EnumPropertyItem *item = NULL; + EnumPropertyItem *input = prop_driver_create_mapping_types; + EnumPropertyItem *item = NULL; - PointerRNA ptr = {{NULL}}; - PropertyRNA *prop = NULL; - int index; + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index; - int totitem = 0; + int totitem = 0; - if (!C) /* needed for docs */ - return prop_driver_create_mapping_types; + if (!C) /* needed for docs */ + return prop_driver_create_mapping_types; - UI_context_active_but_prop_get(C, &ptr, &prop, &index); + UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - const bool is_array = RNA_property_array_check(prop); + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + const bool is_array = RNA_property_array_check(prop); - while (input->identifier) { - if (ELEM(input->value, CREATEDRIVER_MAPPING_1_1, CREATEDRIVER_MAPPING_NONE) || (is_array)) { - RNA_enum_item_add(&item, &totitem, input); - } - input++; - } - } - else { - /* We need at least this one! */ - RNA_enum_items_add_value(&item, &totitem, input, CREATEDRIVER_MAPPING_NONE); - } + while (input->identifier) { + if (ELEM(input->value, CREATEDRIVER_MAPPING_1_1, CREATEDRIVER_MAPPING_NONE) || (is_array)) { + RNA_enum_item_add(&item, &totitem, input); + } + input++; + } + } + else { + /* We need at least this one! */ + RNA_enum_items_add_value(&item, &totitem, input, CREATEDRIVER_MAPPING_NONE); + } - RNA_enum_item_end(&item, &totitem); + RNA_enum_item_end(&item, &totitem); - *r_free = true; - return item; + *r_free = true; + return item; } - /* Add Driver (With Menu) Button Operator ------------------------ */ static bool add_driver_button_poll(bContext *C) { - PointerRNA ptr = {{NULL}}; - PropertyRNA *prop = NULL; - int index; + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index; - /* this operator can only run if there's a property button active, and it can be animated */ - UI_context_active_but_prop_get(C, &ptr, &prop, &index); - return (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)); + /* this operator can only run if there's a property button active, and it can be animated */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + return (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)); } /* Wrapper for creating a driver without knowing what the targets will be yet (i.e. "manual/add later") */ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_type) { - PointerRNA ptr = {{NULL}}; - PropertyRNA *prop = NULL; - int index; - int success = 0; - - UI_context_active_but_prop_get(C, &ptr, &prop, &index); - - if (mapping_type == CREATEDRIVER_MAPPING_NONE_ALL) - index = -1; - - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); - short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; - - if (path) { - success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); - MEM_freeN(path); - } - } - - if (success) { - /* send updates */ - UI_context_update_anim_flag(C); - DEG_relations_tag_update(CTX_data_main(C)); - WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index; + int success = 0; + + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + if (mapping_type == CREATEDRIVER_MAPPING_NONE_ALL) + index = -1; + + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); + short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; + + if (path) { + success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); + MEM_freeN(path); + } + } + + if (success) { + /* send updates */ + UI_context_update_anim_flag(C); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } static int add_driver_button_menu_exec(bContext *C, wmOperator *op) { - short mapping_type = RNA_enum_get(op->ptr, "mapping_type"); - if (ELEM(mapping_type, CREATEDRIVER_MAPPING_NONE, CREATEDRIVER_MAPPING_NONE_ALL)) { - /* Just create driver with no targets */ - return add_driver_button_none(C, op, mapping_type); - } - else { - /* Create Driver using Eyedropper */ - wmOperatorType *ot = WM_operatortype_find("UI_OT_eyedropper_driver", true); - - /* XXX: We assume that it's fine to use the same set of properties, since they're actually the same... */ - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr); - - return OPERATOR_FINISHED; - } + short mapping_type = RNA_enum_get(op->ptr, "mapping_type"); + if (ELEM(mapping_type, CREATEDRIVER_MAPPING_NONE, CREATEDRIVER_MAPPING_NONE_ALL)) { + /* Just create driver with no targets */ + return add_driver_button_none(C, op, mapping_type); + } + else { + /* Create Driver using Eyedropper */ + wmOperatorType *ot = WM_operatortype_find("UI_OT_eyedropper_driver", true); + + /* XXX: We assume that it's fine to use the same set of properties, since they're actually the same... */ + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, op->ptr); + + return OPERATOR_FINISHED; + } } /* Show menu or create drivers */ static int add_driver_button_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - PropertyRNA *prop; - - if ((prop = RNA_struct_find_property(op->ptr, "mapping_type")) && RNA_property_is_set(op->ptr, prop)) { - /* Mapping Type is Set - Directly go into creating drivers */ - return add_driver_button_menu_exec(C, op); - } - else { - /* Show menu */ - // TODO: This should get filtered by the enum filter - /* important to execute in the region we're currently in */ - return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT); - } + PropertyRNA *prop; + + if ((prop = RNA_struct_find_property(op->ptr, "mapping_type")) && + RNA_property_is_set(op->ptr, prop)) { + /* Mapping Type is Set - Directly go into creating drivers */ + return add_driver_button_menu_exec(C, op); + } + else { + /* Show menu */ + // TODO: This should get filtered by the enum filter + /* important to execute in the region we're currently in */ + return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT); + } } static void UNUSED_FUNCTION(ANIM_OT_driver_button_add_menu)(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Driver Menu"; - ot->idname = "ANIM_OT_driver_button_add_menu"; - ot->description = "Add driver(s) for the property(s) represented by the highlighted button"; - - /* callbacks */ - ot->invoke = add_driver_button_menu_invoke; - ot->exec = add_driver_button_menu_exec; - ot->poll = add_driver_button_poll; - - /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; - - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "mapping_type", prop_driver_create_mapping_types, 0, - "Mapping Type", "Method used to match target and driven properties"); - RNA_def_enum_funcs(ot->prop, driver_mapping_type_itemsf); + /* identifiers */ + ot->name = "Add Driver Menu"; + ot->idname = "ANIM_OT_driver_button_add_menu"; + ot->description = "Add driver(s) for the property(s) represented by the highlighted button"; + + /* callbacks */ + ot->invoke = add_driver_button_menu_invoke; + ot->exec = add_driver_button_menu_exec; + ot->poll = add_driver_button_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, + "mapping_type", + prop_driver_create_mapping_types, + 0, + "Mapping Type", + "Method used to match target and driven properties"); + RNA_def_enum_funcs(ot->prop, driver_mapping_type_itemsf); } /* Add Driver Button Operator ------------------------ */ static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - PointerRNA ptr = {{NULL}}; - PropertyRNA *prop = NULL; - int index; - - /* try to find driver using property retrieved from UI */ - UI_context_active_but_prop_get(C, &ptr, &prop, &index); - - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - /* 1) Create a new "empty" driver for this property */ - char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); - short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; - short success = 0; - - if (path) { - success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); - MEM_freeN(path); - } - - if (success) { - /* send updates */ - UI_context_update_anim_flag(C); - DEG_id_tag_update(ptr.id.data, ID_RECALC_COPY_ON_WRITE); - DEG_relations_tag_update(CTX_data_main(C)); - WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); - } - - /* 2) Show editing panel for setting up this driver */ - /* TODO: Use a different one from the editing popever, so we can have the single/all toggle? */ - UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports); - } - - return OPERATOR_INTERFACE; + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index; + + /* try to find driver using property retrieved from UI */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + /* 1) Create a new "empty" driver for this property */ + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); + short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; + short success = 0; + + if (path) { + success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); + MEM_freeN(path); + } + + if (success) { + /* send updates */ + UI_context_update_anim_flag(C); + DEG_id_tag_update(ptr.id.data, ID_RECALC_COPY_ON_WRITE); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); + } + + /* 2) Show editing panel for setting up this driver */ + /* TODO: Use a different one from the editing popever, so we can have the single/all toggle? */ + UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports); + } + + return OPERATOR_INTERFACE; } void ANIM_OT_driver_button_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Driver"; - ot->idname = "ANIM_OT_driver_button_add"; - ot->description = "Add driver for the property under the cursor"; - - /* callbacks */ - /* NOTE: No exec, as we need all these to use the current context info */ - ot->invoke = add_driver_button_invoke; - ot->poll = add_driver_button_poll; - - /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + /* identifiers */ + ot->name = "Add Driver"; + ot->idname = "ANIM_OT_driver_button_add"; + ot->description = "Add driver for the property under the cursor"; + + /* callbacks */ + /* NOTE: No exec, as we need all these to use the current context info */ + ot->invoke = add_driver_button_invoke; + ot->poll = add_driver_button_poll; + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; } /* Remove Driver Button Operator ------------------------ */ static int remove_driver_button_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = {{NULL}}; - PropertyRNA *prop = NULL; - short success = 0; - int index; - const bool all = RNA_boolean_get(op->ptr, "all"); + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + short success = 0; + int index; + const bool all = RNA_boolean_get(op->ptr, "all"); - /* try to find driver using property retrieved from UI */ - UI_context_active_but_prop_get(C, &ptr, &prop, &index); + /* try to find driver using property retrieved from UI */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (all) - index = -1; + if (all) + index = -1; - if (ptr.id.data && ptr.data && prop) { - char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); + if (ptr.id.data && ptr.data && prop) { + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); - if (path) { - success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0); + if (path) { + success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0); - MEM_freeN(path); - } - } + MEM_freeN(path); + } + } - if (success) { - /* send updates */ - UI_context_update_anim_flag(C); - DEG_relations_tag_update(CTX_data_main(C)); - WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX - } + if (success) { + /* send updates */ + UI_context_update_anim_flag(C); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX + } - return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } void ANIM_OT_driver_button_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Driver"; - ot->idname = "ANIM_OT_driver_button_remove"; - ot->description = "Remove the driver(s) for the property(s) connected represented by the highlighted button"; + /* identifiers */ + ot->name = "Remove Driver"; + ot->idname = "ANIM_OT_driver_button_remove"; + ot->description = + "Remove the driver(s) for the property(s) connected represented by the highlighted button"; - /* callbacks */ - ot->exec = remove_driver_button_exec; - //op->poll = ??? // TODO: need to have some driver to be able to do this... + /* callbacks */ + ot->exec = remove_driver_button_exec; + //op->poll = ??? // TODO: need to have some driver to be able to do this... - /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; - /* properties */ - RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array"); + /* properties */ + RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array"); } /* Edit Driver Button Operator ------------------------ */ static int edit_driver_button_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = {{NULL}}; - PropertyRNA *prop = NULL; - int index; + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index; - /* try to find driver using property retrieved from UI */ - UI_context_active_but_prop_get(C, &ptr, &prop, &index); + /* try to find driver using property retrieved from UI */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop) { - UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports); - } + if (ptr.id.data && ptr.data && prop) { + UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports); + } - return OPERATOR_INTERFACE; + return OPERATOR_INTERFACE; } void ANIM_OT_driver_button_edit(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Edit Driver"; - ot->idname = "ANIM_OT_driver_button_edit"; - ot->description = "Edit the drivers for the property connected represented by the highlighted button"; - - /* callbacks */ - ot->exec = edit_driver_button_exec; - //op->poll = ??? // TODO: need to have some driver to be able to do this... - - /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + /* identifiers */ + ot->name = "Edit Driver"; + ot->idname = "ANIM_OT_driver_button_edit"; + ot->description = + "Edit the drivers for the property connected represented by the highlighted button"; + + /* callbacks */ + ot->exec = edit_driver_button_exec; + //op->poll = ??? // TODO: need to have some driver to be able to do this... + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; } /* Copy Driver Button Operator ------------------------ */ static int copy_driver_button_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = {{NULL}}; - PropertyRNA *prop = NULL; - short success = 0; - int index; + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + short success = 0; + int index; - /* try to create driver using property retrieved from UI */ - UI_context_active_but_prop_get(C, &ptr, &prop, &index); + /* try to create driver using property retrieved from UI */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); - if (path) { - /* only copy the driver for the button that this was involved for */ - success = ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0); + if (path) { + /* only copy the driver for the button that this was involved for */ + success = ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0); - UI_context_update_anim_flag(C); + UI_context_update_anim_flag(C); - MEM_freeN(path); - } - } + MEM_freeN(path); + } + } - /* since we're just copying, we don't really need to do anything else...*/ - return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + /* since we're just copying, we don't really need to do anything else...*/ + return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } void ANIM_OT_copy_driver_button(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Driver"; - ot->idname = "ANIM_OT_copy_driver_button"; - ot->description = "Copy the driver for the highlighted button"; + /* identifiers */ + ot->name = "Copy Driver"; + ot->idname = "ANIM_OT_copy_driver_button"; + ot->description = "Copy the driver for the highlighted button"; - /* callbacks */ - ot->exec = copy_driver_button_exec; - //op->poll = ??? // TODO: need to have some driver to be able to do this... + /* callbacks */ + ot->exec = copy_driver_button_exec; + //op->poll = ??? // TODO: need to have some driver to be able to do this... - /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; } /* Paste Driver Button Operator ------------------------ */ static int paste_driver_button_exec(bContext *C, wmOperator *op) { - PointerRNA ptr = {{NULL}}; - PropertyRNA *prop = NULL; - short success = 0; - int index; + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + short success = 0; + int index; - /* try to create driver using property retrieved from UI */ - UI_context_active_but_prop_get(C, &ptr, &prop, &index); + /* try to create driver using property retrieved from UI */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); - if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); + if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); - if (path) { - /* only copy the driver for the button that this was involved for */ - success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0); + if (path) { + /* only copy the driver for the button that this was involved for */ + success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0); - UI_context_update_anim_flag(C); + UI_context_update_anim_flag(C); - DEG_relations_tag_update(CTX_data_main(C)); - DEG_id_tag_update(ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + DEG_relations_tag_update(CTX_data_main(C)); + DEG_id_tag_update(ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX - MEM_freeN(path); - } - } + MEM_freeN(path); + } + } - /* since we're just copying, we don't really need to do anything else...*/ - return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + /* since we're just copying, we don't really need to do anything else...*/ + return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } void ANIM_OT_paste_driver_button(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste Driver"; - ot->idname = "ANIM_OT_paste_driver_button"; - ot->description = "Paste the driver in the copy/paste buffer for the highlighted button"; + /* identifiers */ + ot->name = "Paste Driver"; + ot->idname = "ANIM_OT_paste_driver_button"; + ot->description = "Paste the driver in the copy/paste buffer for the highlighted button"; - /* callbacks */ - ot->exec = paste_driver_button_exec; - //op->poll = ??? // TODO: need to have some driver to be able to do this... + /* callbacks */ + ot->exec = paste_driver_button_exec; + //op->poll = ??? // TODO: need to have some driver to be able to do this... - /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; } /* ************************************************** */ -- cgit v1.2.3