diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/animation/drivers.c | 136 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframing.h | 8 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_context_menu.c | 7 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_ops.c | 81 |
4 files changed, 186 insertions, 46 deletions
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 7ca0f95d6c4..935d11a388f 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -23,6 +23,7 @@ #include <stdio.h> #include <string.h> +#include <ctype.h> #include "MEM_guardedalloc.h" @@ -95,56 +96,65 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde if ((fcu == NULL) && (add)) { /* use default settings to make a F-Curve */ - fcu = MEM_callocN(sizeof(FCurve), "FCurve"); + fcu = alloc_driver_fcurve(rna_path, array_index, add); - fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED); - fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL; + /* just add F-Curve to end of driver list */ + BLI_addtail(&adt->drivers, fcu); + } - /* 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); + /* return the F-Curve */ + return fcu; +} - /* configure this curve to extrapolate */ - for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) { - bezt->h1 = bezt->h2 = HD_VECT; - } +struct FCurve *alloc_driver_fcurve(const char rna_path[], const int array_index, short add) +{ + FCurve *fcu = MEM_callocN(sizeof(FCurve), "FCurve"); - fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; - calchandles_fcurve(fcu); - } + fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED); + fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL; + + /* store path - make copy, and store that */ + if (rna_path) { + 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); - /* just add F-Curve to end of driver list */ - BLI_addtail(&adt->drivers, fcu); + /* 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); + } } - /* return the F-Curve */ return fcu; } @@ -834,6 +844,48 @@ bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace) return true; } +/* -------------------------------------------------- */ + +/* Create a driver & variable that reads the specified property, + * and store it in the buffers for Paste Driver and Paste Variables. */ +void ANIM_copy_as_driver(struct ID *target_id, const char *target_path, const char *var_name) +{ + /* Clear copy/paste buffer first (for consistency with other copy/paste buffers). */ + ANIM_drivers_copybuf_free(); + ANIM_driver_vars_copybuf_free(); + + /* Create a dummy driver F-Curve. */ + FCurve *fcu = alloc_driver_fcurve(NULL, 0, 1); + ChannelDriver *driver = fcu->driver; + + /* Create a variable. */ + DriverVar *var = driver_add_new_variable(driver); + DriverTarget *target = &var->targets[0]; + + target->idtype = GS(target_id->name); + target->id = target_id; + target->rna_path = MEM_dupallocN(target_path); + + /* Set the variable name. */ + if (var_name) { + BLI_strncpy(var->name, var_name, sizeof(var->name)); + + /* Sanitize the name. */ + for (int i = 0; var->name[i]; i++) { + if (!(i > 0 ? isalnum(var->name[i]) : isalpha(var->name[i]))) { + var->name[i] = '_'; + } + } + } + + BLI_strncpy(driver->expression, var->name, sizeof(driver->expression)); + + /* Store the driver into the copy/paste buffers. */ + channeldriver_copypaste_buf = fcu; + + driver_variables_copy(&driver_vars_copybuf, &driver->variables); +} + /* ************************************************** */ /* UI-Button Interface */ diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 8f197fa9afe..bbeeeade822 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -320,6 +320,8 @@ struct FCurve *verify_driver_fcurve(struct ID *id, const int array_index, short add); +struct FCurve *alloc_driver_fcurve(const char rna_path[], const int array_index, short add); + /* -------- */ /* Main Driver Management API calls: @@ -399,6 +401,12 @@ bool ANIM_driver_vars_copy(struct ReportList *reports, struct FCurve *fcu); /* Paste the variables in the buffer to the given FCurve */ bool ANIM_driver_vars_paste(struct ReportList *reports, struct FCurve *fcu, bool replace); +/* -------- */ + +/* Create a driver & variable that reads the specified property, + * and store it in the buffers for Paste Driver and Paste Variables. */ +void ANIM_copy_as_driver(struct ID *target_id, const char *target_path, const char *var_name); + /* ************ Auto-Keyframing ********************** */ /* Notes: * - All the defines for this (User-Pref settings and Per-Scene settings) diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 7cec8af46de..88fe8704082 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -899,6 +899,13 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) ICON_NONE, "UI_OT_copy_data_path_button"); + if (ptr->id.data && ELEM(type, PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) { + uiItemO(layout, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy As New Driver"), + ICON_NONE, + "UI_OT_copy_as_driver_button"); + } + uiItemS(layout); if (type == PROP_STRING && ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) { diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index f2b2a478ba9..f5a894d7620 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -65,6 +65,9 @@ #include "ED_object.h" #include "ED_paint.h" +/* for Copy As Driver */ +#include "ED_keyframing.h" + /* only for UI_OT_editsource */ #include "ED_screen.h" #include "BKE_main.h" @@ -153,23 +156,92 @@ static void UI_OT_copy_data_path_button(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -static bool copy_python_command_button_poll(bContext *C) +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy As Driver Operator + * \{ */ + +static bool copy_as_driver_button_poll(bContext *C) { - uiBut *but = UI_context_active_but_get(C); + PointerRNA ptr; + PropertyRNA *prop; + char *path; + int index; - if (but && (but->optype != NULL)) { - return 1; + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + if (ptr.id.data && ptr.data && prop && + ELEM(RNA_property_type(prop), PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) { + path = RNA_path_from_ID_to_property(&ptr, prop); + + if (path) { + MEM_freeN(path); + return 1; + } } return 0; } +static int copy_as_driver_button_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr; + PropertyRNA *prop; + int 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) { + int dim = RNA_property_array_dimension(&ptr, prop, NULL); + char *path = RNA_path_from_ID_to_property_index(&ptr, prop, dim, index); + + if (path) { + ANIM_copy_as_driver(ptr.id.data, path, RNA_property_identifier(prop)); + MEM_freeN(path); + return OPERATOR_FINISHED; + } + } + + return OPERATOR_CANCELLED; +} + +static void UI_OT_copy_as_driver_button(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Copy As New Driver"; + ot->idname = "UI_OT_copy_as_driver_button"; + ot->description = + "Create a new driver with this property as input, and copy it to the " + "clipboard. Use Paste Driver to add it to the target property, or Paste " + "Driver Variables to extend an existing driver"; + + /* callbacks */ + ot->exec = copy_as_driver_button_exec; + ot->poll = copy_as_driver_button_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + /** \} */ /* -------------------------------------------------------------------- */ /** \name Copy Python Command Operator * \{ */ +static bool copy_python_command_button_poll(bContext *C) +{ + uiBut *but = UI_context_active_but_get(C); + + if (but && (but->optype != NULL)) { + return 1; + } + + return 0; +} + static int copy_python_command_button_exec(bContext *C, wmOperator *UNUSED(op)) { uiBut *but = UI_context_active_but_get(C); @@ -1668,6 +1740,7 @@ static void UI_OT_drop_color(wmOperatorType *ot) void ED_operatortypes_ui(void) { WM_operatortype_append(UI_OT_copy_data_path_button); + WM_operatortype_append(UI_OT_copy_as_driver_button); WM_operatortype_append(UI_OT_copy_python_command_button); WM_operatortype_append(UI_OT_reset_default_button); WM_operatortype_append(UI_OT_assign_default_button); |