Drivers: Copy/Paste tools for the RMB Menu

Drivers can now be copied/pasted for single properties, allowing drivers set up on one property to be added to a few other properties relatively easily. 

Also, added description strings for the other driver-button operators.
This commit is contained in:
Joshua Leung 2009-09-25 04:51:04 +00:00
parent 0aa08fce72
commit 2d22ea1f92
8 changed files with 271 additions and 13 deletions

@ -688,7 +688,7 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) { \
bPoseChannel *pchan= get_pose_channel(ct->tar->pose, ct->subtarget); \
ct->type = CONSTRAINT_OBTYPE_BONE; \
ct->rotOrder= pchan->rotmode; \
ct->rotOrder= (pchan) ? (pchan->rotmode) : EULER_ORDER_DEFAULT; \
}\
else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { \
ct->type = CONSTRAINT_OBTYPE_VERT; \

@ -399,6 +399,8 @@ void ED_operatortypes_anim(void)
WM_operatortype_append(ANIM_OT_add_driver_button);
WM_operatortype_append(ANIM_OT_remove_driver_button);
WM_operatortype_append(ANIM_OT_copy_driver_button);
WM_operatortype_append(ANIM_OT_paste_driver_button);
WM_operatortype_append(ANIM_OT_add_keyingset_button);
WM_operatortype_append(ANIM_OT_remove_keyingset_button);

@ -80,6 +80,10 @@
/* Get (or add relevant data to be able to do so) F-Curve from the driver stack,
* for the given Animation Data block. This assumes that all the destinations are valid.
*
* - add: 0 - don't add anything if not found,
* 1 - add new Driver FCurve,
* -1 - add new Driver FCurve without driver stuff (for pasting)
*/
FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add)
{
@ -115,11 +119,14 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind
fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
fcu->array_index= array_index;
/* add some new driver data */
fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
/* add simple generator modifier for driver so that there is some visible representation */
add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
/* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */
if (add > 0) {
/* add some new driver data */
fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
/* add simple generator modifier for driver so that there is some visible representation */
add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
}
/* just add F-Curve to end of driver list */
BLI_addtail(&adt->drivers, fcu);
@ -144,7 +151,7 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla
/* validate pointer first - exit if failure */
RNA_id_pointer_create(id, &id_ptr);
if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
printf("Insert Key: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
printf("Add Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
return 0;
}
@ -163,7 +170,7 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla
float fval;
if (proptype == PROP_BOOLEAN) {
if(!array) val= RNA_property_boolean_get(&ptr, prop);
if (!array) val= RNA_property_boolean_get(&ptr, prop);
else val= RNA_property_boolean_get_index(&ptr, prop, array_index);
BLI_strncpy(expression, (val)? "True": "False", maxlen);
@ -180,7 +187,6 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla
BLI_snprintf(expression, maxlen, "%.3f", fval);
}
}
}
@ -218,6 +224,127 @@ short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index,
return 0;
}
/* ************************************************** */
/* Driver Management API - Copy/Paste Drivers */
/* Copy/Paste Buffer for Driver Data... */
static FCurve *channeldriver_copypaste_buf = NULL;
/* This function frees any MEM_calloc'ed copy/paste buffer data */
// XXX find some header to put this in!
void free_anim_drivers_copybuf (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;
}
/* Checks if there is a driver in the copy/paste buffer */
short ANIM_driver_can_paste (void)
{
return (channeldriver_copypaste_buf != NULL);
}
/* ------------------- */
/* Main Driver Management API calls:
* Make a copy of the driver for the specified property on the given ID block
*/
short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short 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(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
printf("Copy Driver: Could not find Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", 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) */
free_anim_drivers_copybuf();
/* 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
*/
short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short 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(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
printf("Paste Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
return 0;
}
/* if the buffer is empty, cannot paste... */
if (channeldriver_copypaste_buf == NULL) {
printf("Paste Driver: No Driver to paste. \n");
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);
/* flags - on a per-relevant-flag basis */
if (channeldriver_copypaste_buf->flag & FCURVE_AUTO_HANDLES)
fcu->flag |= FCURVE_AUTO_HANDLES;
else
fcu->flag &= ~FCURVE_AUTO_HANDLES;
/* 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);
}
/* ************************************************** */
/* UI-Button Interface */
@ -272,10 +399,11 @@ void ANIM_OT_add_driver_button (wmOperatorType *ot)
/* identifiers */
ot->name= "Add Driver";
ot->idname= "ANIM_OT_add_driver_button";
ot->description= "Add driver(s) for the property(s) connected represented by the highlighted button.";
/* callbacks */
ot->exec= add_driver_button_exec;
//op->poll= ???
//op->poll= ??? // TODO: need to have some animateable property to do this
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -335,10 +463,11 @@ void ANIM_OT_remove_driver_button (wmOperatorType *ot)
/* identifiers */
ot->name= "Remove Driver";
ot->idname= "ANIM_OT_remove_driver_button";
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= ???
//op->poll= ??? // TODO: need to have some driver to be able to do this...
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@ -347,4 +476,92 @@ void ANIM_OT_remove_driver_button (wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array.");
}
/* Copy Driver Button Operator ------------------------ */
static int copy_driver_button_exec (bContext *C, wmOperator *op)
{
PointerRNA ptr;
PropertyRNA *prop= NULL;
char *path;
short success= 0;
int index;
/* try to create driver using property retrieved from UI */
memset(&ptr, 0, sizeof(PointerRNA));
uiAnimContextProperty(C, &ptr, &prop, &index);
if (ptr.data && prop && RNA_property_animateable(ptr.data, prop)) {
path= RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
/* only copy the driver for the button that this was involved for */
success= ANIM_copy_driver(ptr.id.data, path, index, 0);
MEM_freeN(path);
}
}
/* 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.";
/* 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_REGISTER|OPTYPE_UNDO;
}
/* Paste Driver Button Operator ------------------------ */
static int paste_driver_button_exec (bContext *C, wmOperator *op)
{
PointerRNA ptr;
PropertyRNA *prop= NULL;
char *path;
short success= 0;
int index;
/* try to create driver using property retrieved from UI */
memset(&ptr, 0, sizeof(PointerRNA));
uiAnimContextProperty(C, &ptr, &prop, &index);
if (ptr.data && prop && RNA_property_animateable(ptr.data, prop)) {
path= RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
/* only copy the driver for the button that this was involved for */
success= ANIM_paste_driver(ptr.id.data, path, index, 0);
MEM_freeN(path);
}
}
/* 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.";
/* 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_REGISTER|OPTYPE_UNDO;
}
/* ************************************************** */

@ -163,6 +163,9 @@ void ANIM_OT_remove_keyingset_button(struct wmOperatorType *ot);
/* ************ Drivers ********************** */
/* Returns whether there is a driver in the copy/paste buffer to paste */
short ANIM_driver_can_paste(void);
/* Main Driver Management API calls:
* Add a new driver for the specified property on the given ID block
*/
@ -171,11 +174,24 @@ short ANIM_add_driver (struct ID *id, const char rna_path[], int array_index, sh
/* Main Driver Management API calls:
* Remove the driver for the specified property on the given ID block (if available)
*/
short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag);
short ANIM_remove_driver(struct ID *id, const char rna_path[], int array_index, short flag);
/* Main Driver Management API calls:
* Make a copy of the driver for the specified property on the given ID block
*/
short ANIM_copy_driver(struct ID *id, const char rna_path[], int array_index, short flag);
/* 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
*/
short ANIM_paste_driver(struct ID *id, const char rna_path[], int array_index, short flag);
/* Driver management operators for UI buttons */
void ANIM_OT_add_driver_button(struct wmOperatorType *ot);
void ANIM_OT_remove_driver_button(struct wmOperatorType *ot);
void ANIM_OT_copy_driver_button(struct wmOperatorType *ot);
void ANIM_OT_paste_driver_button(struct wmOperatorType *ot);
/* ************ Auto-Keyframing ********************** */
/* Notes:

@ -209,6 +209,18 @@ void ui_but_anim_remove_driver(bContext *C)
WM_operator_name_call(C, "ANIM_OT_remove_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_copy_driver(bContext *C)
{
/* this operator calls uiAnimContextProperty above */
WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_paste_driver(bContext *C)
{
/* this operator calls uiAnimContextProperty above */
WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
}
void ui_but_anim_add_keyingset(bContext *C)
{
/* this operator calls uiAnimContextProperty above */
@ -264,6 +276,10 @@ void ui_but_anim_menu(bContext *C, uiBut *but)
}
else
uiItemBooleanO(layout, "Delete Driver", 0, "ANIM_OT_remove_driver_button", "all", 0);
uiItemO(layout, "Copy Driver", 0, "ANIM_OT_copy_driver_button");
if (ANIM_driver_can_paste())
uiItemO(layout, "Paste Driver", 0, "ANIM_OT_paste_driver_button");
}
else if(but->flag & UI_BUT_ANIMATED_KEY);
else if(RNA_property_animateable(&but->rnapoin, but->rnaprop)) {
@ -275,6 +291,9 @@ void ui_but_anim_menu(bContext *C, uiBut *but)
}
else
uiItemBooleanO(layout, "Add Driver", 0, "ANIM_OT_add_driver_button", "all", 0);
if (ANIM_driver_can_paste())
uiItemO(layout, "Paste Driver", 0, "ANIM_OT_paste_driver_button");
}
if(RNA_property_animateable(&but->rnapoin, but->rnaprop)) {

@ -470,6 +470,8 @@ void ui_but_anim_insert_keyframe(struct bContext *C);
void ui_but_anim_delete_keyframe(struct bContext *C);
void ui_but_anim_add_driver(struct bContext *C);
void ui_but_anim_remove_driver(struct bContext *C);
void ui_but_anim_copy_driver(struct bContext *C);
void ui_but_anim_paste_driver(struct bContext *C);
void ui_but_anim_add_keyingset(struct bContext *C);
void ui_but_anim_remove_keyingset(struct bContext *C);
void ui_but_anim_menu(struct bContext *C, uiBut *but);

@ -480,7 +480,7 @@ static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr,
static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h, int icon_only)
{
uiLayout *sub;
uiBut *but;
uiBut *but=NULL;
PropertyType type;
PropertySubType subtype;
int labelw;

@ -166,6 +166,7 @@ extern wchar_t *copybufinfo;
// XXX copy/paste buffer stuff...
extern void free_anim_copybuf();
extern void free_anim_drivers_copybuf();
extern void free_posebuf();
/* called in creator.c even... tsk, split this! */
@ -213,6 +214,7 @@ void WM_exit(bContext *C)
free_blender(); /* blender.c, does entire library and spacetypes */
// free_matcopybuf();
free_anim_copybuf();
free_anim_drivers_copybuf();
free_posebuf();
// free_vertexpaint();
// free_imagepaint();