2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-07-02 05:25:14 +00:00
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-07-02 05:25:14 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
*
|
|
|
|
* Contributor(s): Joshua Leung (full recode)
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
2009-04-10 13:08:12 +00:00
|
|
|
*/
|
2011-02-27 20:29:51 +00:00
|
|
|
|
|
|
|
/** \file blender/editors/animation/drivers.c
|
|
|
|
* \ingroup edanimation
|
|
|
|
*/
|
|
|
|
|
2009-04-10 13:08:12 +00:00
|
|
|
|
2011-01-14 02:06:35 +00:00
|
|
|
#include <stdio.h>
|
2009-04-10 13:08:12 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
#include "DNA_anim_types.h"
|
2011-01-14 02:06:35 +00:00
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_material_types.h"
|
|
|
|
#include "DNA_texture_types.h"
|
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
#include "DNA_space_types.h"
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
#include "BKE_animsys.h"
|
2009-11-25 09:25:58 +00:00
|
|
|
#include "BKE_depsgraph.h"
|
2009-04-10 13:08:12 +00:00
|
|
|
#include "BKE_fcurve.h"
|
|
|
|
#include "BKE_context.h"
|
2010-12-28 05:45:15 +00:00
|
|
|
#include "BKE_report.h"
|
2011-01-14 02:06:35 +00:00
|
|
|
#include "BKE_material.h"
|
|
|
|
#include "BKE_texture.h"
|
2010-12-28 05:45:15 +00:00
|
|
|
|
|
|
|
#include "ED_keyframing.h"
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
#include "UI_interface.h"
|
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "RNA_define.h"
|
|
|
|
|
2011-02-13 10:52:18 +00:00
|
|
|
#include "anim_intern.h"
|
|
|
|
|
|
|
|
/* called by WM */
|
|
|
|
void free_anim_drivers_copybuf (void);
|
|
|
|
|
2009-04-10 13:08:12 +00:00
|
|
|
/* ************************************************** */
|
|
|
|
/* Animation Data Validation */
|
|
|
|
|
|
|
|
/* 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.
|
2009-09-25 04:51:04 +00:00
|
|
|
*
|
|
|
|
* - add: 0 - don't add anything if not found,
|
|
|
|
* 1 - add new Driver FCurve,
|
|
|
|
* -1 - add new Driver FCurve without driver stuff (for pasting)
|
2009-04-10 13:08:12 +00:00
|
|
|
*/
|
2011-02-13 14:16:36 +00:00
|
|
|
static FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add)
|
2009-04-10 13:08:12 +00:00
|
|
|
{
|
|
|
|
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_id_add_animdata(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_AUTO_HANDLES|FCURVE_SELECTED);
|
|
|
|
|
|
|
|
/* store path - make copy, and store that */
|
|
|
|
fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
|
|
|
|
fcu->array_index= array_index;
|
|
|
|
|
2009-09-25 04:51:04 +00:00
|
|
|
/* 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);
|
|
|
|
}
|
2009-04-10 13:16:50 +00:00
|
|
|
|
2009-04-10 13:08:12 +00:00
|
|
|
/* just add F-Curve to end of driver list */
|
|
|
|
BLI_addtail(&adt->drivers, fcu);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return the F-Curve */
|
|
|
|
return fcu;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************** */
|
|
|
|
/* Driver Management API */
|
|
|
|
|
|
|
|
/* Main Driver Management API calls:
|
|
|
|
* Add a new driver for the specified property on the given ID block
|
|
|
|
*/
|
2010-12-28 05:45:15 +00:00
|
|
|
short ANIM_add_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
|
2009-04-10 13:08:12 +00:00
|
|
|
{
|
|
|
|
PointerRNA id_ptr, ptr;
|
|
|
|
PropertyRNA *prop;
|
|
|
|
FCurve *fcu;
|
2009-11-19 00:37:47 +00:00
|
|
|
int array_index_max;
|
2009-11-08 06:43:08 +00:00
|
|
|
int done = 0;
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
/* 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)) {
|
2010-12-28 05:45:15 +00:00
|
|
|
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);
|
2009-04-10 13:08:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-11-05 08:54:33 +00:00
|
|
|
/* key entire array convenience method */
|
|
|
|
if (array_index == -1) {
|
2009-11-17 14:10:29 +00:00
|
|
|
array_index_max= RNA_property_array_length(&ptr, prop);
|
2009-11-19 00:37:47 +00:00
|
|
|
array_index= 0;
|
2009-11-04 15:16:41 +00:00
|
|
|
}
|
2009-11-19 00:37:47 +00:00
|
|
|
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;
|
2009-11-05 08:54:33 +00:00
|
|
|
|
2009-11-04 15:16:41 +00:00
|
|
|
/* will only loop once unless the array index was -1 */
|
2009-11-05 08:54:33 +00:00
|
|
|
for (; array_index < array_index_max; array_index++) {
|
2009-11-04 15:16:41 +00:00
|
|
|
/* create F-Curve with Driver */
|
|
|
|
fcu= verify_driver_fcurve(id, rna_path, array_index, 1);
|
2009-11-05 08:54:33 +00:00
|
|
|
|
2009-11-04 15:16:41 +00:00
|
|
|
if (fcu && fcu->driver) {
|
2009-11-25 09:25:58 +00:00
|
|
|
ChannelDriver *driver= fcu->driver;
|
|
|
|
|
|
|
|
/* set the type of the driver */
|
|
|
|
driver->type= type;
|
2009-09-04 11:19:12 +00:00
|
|
|
|
2010-12-28 05:45:15 +00:00
|
|
|
/* 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
|
|
|
|
*/
|
2009-11-04 15:16:41 +00:00
|
|
|
if (type == DRIVER_TYPE_PYTHON) {
|
|
|
|
PropertyType proptype= RNA_property_type(prop);
|
|
|
|
int array= RNA_property_array_length(&ptr, prop);
|
2009-11-25 09:25:58 +00:00
|
|
|
char *expression= driver->expression;
|
|
|
|
int val, maxlen= sizeof(driver->expression);
|
2009-11-04 15:16:41 +00:00
|
|
|
float fval;
|
2009-09-04 11:19:12 +00:00
|
|
|
|
2009-11-04 15:16:41 +00:00
|
|
|
if (proptype == PROP_BOOLEAN) {
|
|
|
|
if (!array) val= RNA_property_boolean_get(&ptr, prop);
|
|
|
|
else val= RNA_property_boolean_get_index(&ptr, prop, array_index);
|
2009-11-05 08:54:33 +00:00
|
|
|
|
2009-11-04 15:16:41 +00:00
|
|
|
BLI_strncpy(expression, (val)? "True": "False", maxlen);
|
|
|
|
}
|
|
|
|
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);
|
2009-11-05 08:54:33 +00:00
|
|
|
|
2009-11-04 15:16:41 +00:00
|
|
|
BLI_snprintf(expression, maxlen, "%d", 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);
|
2009-11-05 08:54:33 +00:00
|
|
|
|
2009-11-04 15:16:41 +00:00
|
|
|
BLI_snprintf(expression, maxlen, "%.3f", fval);
|
|
|
|
}
|
2009-07-12 02:06:15 +00:00
|
|
|
}
|
2010-12-28 05:45:15 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
2009-07-12 02:06:15 +00:00
|
|
|
}
|
2009-11-08 06:43:08 +00:00
|
|
|
|
|
|
|
/* set the done status */
|
|
|
|
done += (fcu != NULL);
|
2009-07-12 02:06:15 +00:00
|
|
|
}
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
/* done */
|
2009-11-08 06:43:08 +00:00
|
|
|
return done;
|
2009-04-10 13:08:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Main Driver Management API calls:
|
|
|
|
* Remove the driver for the specified property on the given ID block (if available)
|
|
|
|
*/
|
2010-12-30 12:22:28 +00:00
|
|
|
short ANIM_remove_driver (ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag))
|
2009-04-10 13:08:12 +00:00
|
|
|
{
|
|
|
|
AnimData *adt;
|
|
|
|
FCurve *fcu;
|
2010-04-11 09:13:37 +00:00
|
|
|
int success= 0;
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
/* we don't check the validity of the path here yet, but it should be ok... */
|
|
|
|
adt= BKE_animdata_from_id(id);
|
|
|
|
|
2010-12-28 05:45:15 +00:00
|
|
|
if (adt) {
|
|
|
|
if (array_index == -1) {
|
|
|
|
/* step through all drivers, removing all of those with the same base path */
|
2010-04-11 09:13:37 +00:00
|
|
|
FCurve *fcu_iter= adt->drivers.first;
|
2010-12-28 05:45:15 +00:00
|
|
|
|
|
|
|
while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) {
|
2010-04-11 09:13:37 +00:00
|
|
|
/* 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 |= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2010-12-28 05:45:15 +00:00
|
|
|
/* 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
|
|
|
|
*/
|
2010-04-11 09:13:37 +00:00
|
|
|
fcu= verify_driver_fcurve(id, rna_path, array_index, 0);
|
2010-12-28 05:45:15 +00:00
|
|
|
if (fcu) {
|
2010-04-11 09:13:37 +00:00
|
|
|
BLI_remlink(&adt->drivers, fcu);
|
|
|
|
free_fcurve(fcu);
|
|
|
|
|
|
|
|
success = 1;
|
|
|
|
}
|
|
|
|
}
|
2009-04-10 13:08:12 +00:00
|
|
|
}
|
2010-04-11 09:13:37 +00:00
|
|
|
|
|
|
|
return success;
|
2009-04-10 13:08:12 +00:00
|
|
|
}
|
|
|
|
|
2009-09-25 04:51:04 +00:00
|
|
|
/* ************************************************** */
|
|
|
|
/* 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
|
|
|
|
*/
|
2010-12-28 05:45:15 +00:00
|
|
|
short ANIM_copy_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
|
2009-09-25 04:51:04 +00:00
|
|
|
{
|
|
|
|
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)) {
|
2010-12-28 05:45:15 +00:00
|
|
|
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);
|
2009-09-25 04:51:04 +00:00
|
|
|
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
|
|
|
|
*/
|
2010-12-28 05:45:15 +00:00
|
|
|
short ANIM_paste_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
|
2009-09-25 04:51:04 +00:00
|
|
|
{
|
|
|
|
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)) {
|
2010-12-28 05:45:15 +00:00
|
|
|
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);
|
2009-09-25 04:51:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if the buffer is empty, cannot paste... */
|
|
|
|
if (channeldriver_copypaste_buf == NULL) {
|
2010-12-28 05:45:15 +00:00
|
|
|
BKE_report(reports, RPT_ERROR, "Paste Driver: No Driver to paste.");
|
2009-09-25 04:51:04 +00:00
|
|
|
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);
|
|
|
|
}
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
/* ************************************************** */
|
|
|
|
/* UI-Button Interface */
|
|
|
|
|
2011-01-14 02:06:35 +00:00
|
|
|
/* Temporary wrapper for driver operators for buttons to make it easier to create
|
|
|
|
* such drivers by rerouting all paths through the active object instead so that
|
|
|
|
* they will get picked up by the dependency system.
|
|
|
|
*
|
|
|
|
* < C: context pointer - for getting active data
|
|
|
|
* <> ptr: RNA pointer for property's datablock. May be modified as result of path remapping.
|
|
|
|
* < prop: RNA definition of property to add for
|
|
|
|
*
|
|
|
|
* > returns: MEM_alloc'd string representing the path to the property from the given PointerRNA
|
|
|
|
*/
|
|
|
|
static char *get_driver_path_hack (bContext *C, PointerRNA *ptr, PropertyRNA *prop)
|
|
|
|
{
|
|
|
|
ID *id = (ID *)ptr->id.data;
|
|
|
|
ScrArea *sa = CTX_wm_area(C);
|
|
|
|
|
|
|
|
/* get standard path which may be extended */
|
|
|
|
char *basepath = RNA_path_from_ID_to_property(ptr, prop);
|
|
|
|
char *path = basepath; /* in case no remapping is needed */
|
|
|
|
|
|
|
|
/* Remapping will only be performed in the Properties Editor, as only this
|
|
|
|
* restricts the subspace of options to the 'active' data (a manageable state)
|
|
|
|
*/
|
|
|
|
// TODO: watch out for pinned context?
|
|
|
|
if ((sa) && (sa->spacetype == SPACE_BUTS)) {
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
|
|
|
|
if (ob && id) {
|
|
|
|
/* only id-types which can be remapped to go through objects should be considered */
|
|
|
|
switch (GS(id->name)) {
|
|
|
|
case ID_MA: /* materials */
|
|
|
|
{
|
|
|
|
Material *ma = give_current_material(ob, ob->actcol);
|
|
|
|
|
|
|
|
/* assumes: material will only be shown if it is active objects's active material it's ok */
|
|
|
|
if ((ID*)ma == id) {
|
|
|
|
/* create new path */
|
|
|
|
// TODO: use RNA path functions to construct instead?
|
|
|
|
path = BLI_sprintfN("material_slots[\"%s\"].material.%s",
|
|
|
|
ma->id.name+2, basepath);
|
|
|
|
|
|
|
|
/* free old one */
|
|
|
|
MEM_freeN(basepath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ID_TE: /* textures */
|
|
|
|
{
|
|
|
|
Material *ma = give_current_material(ob, ob->actcol);
|
|
|
|
Tex *tex = give_current_material_texture(ma);
|
|
|
|
|
|
|
|
/* assumes: texture will only be shown if it is active material's active texture it's ok */
|
|
|
|
if ((ID*)tex == id) {
|
|
|
|
/* create new path */
|
|
|
|
// TODO: use RNA path functions to construct step by step instead?
|
|
|
|
path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s",
|
|
|
|
ma->id.name+2, tex->id.name+2, basepath);
|
|
|
|
|
|
|
|
/* free old one */
|
|
|
|
MEM_freeN(basepath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fix RNA pointer, as we've now changed the ID root by changing the paths */
|
|
|
|
if (basepath != path) {
|
|
|
|
/* rebase provided pointer so that it starts from object... */
|
|
|
|
RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the path should now have been corrected for use */
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2009-04-10 13:08:12 +00:00
|
|
|
/* Add Driver Button Operator ------------------------ */
|
|
|
|
|
|
|
|
static int add_driver_button_exec (bContext *C, wmOperator *op)
|
|
|
|
{
|
2011-02-13 10:52:18 +00:00
|
|
|
PointerRNA ptr= {{NULL}};
|
2009-04-10 13:08:12 +00:00
|
|
|
PropertyRNA *prop= NULL;
|
|
|
|
short success= 0;
|
2009-11-06 22:51:08 +00:00
|
|
|
int index, all= RNA_boolean_get(op->ptr, "all");
|
2009-04-10 13:08:12 +00:00
|
|
|
|
2009-09-04 11:19:12 +00:00
|
|
|
/* try to create driver using property retrieved from UI */
|
2010-09-25 14:32:26 +00:00
|
|
|
uiContextActiveProperty(C, &ptr, &prop, &index);
|
2011-01-14 02:06:35 +00:00
|
|
|
|
2009-11-04 15:16:41 +00:00
|
|
|
if (all)
|
|
|
|
index= -1;
|
2011-01-14 02:06:35 +00:00
|
|
|
|
2010-09-23 20:26:03 +00:00
|
|
|
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
|
2011-01-14 02:06:35 +00:00
|
|
|
char *path= get_driver_path_hack(C, &ptr, prop);
|
2010-12-28 05:45:15 +00:00
|
|
|
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
|
2009-04-10 13:08:12 +00:00
|
|
|
|
2009-11-04 15:16:41 +00:00
|
|
|
if (path) {
|
2010-12-28 05:45:15 +00:00
|
|
|
success+= ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
MEM_freeN(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
/* send updates */
|
2010-09-25 14:32:26 +00:00
|
|
|
uiContextAnimUpdate(C);
|
2010-12-28 05:45:15 +00:00
|
|
|
|
2010-08-01 12:47:49 +00:00
|
|
|
DAG_ids_flush_update(CTX_data_main(C), 0);
|
2009-04-10 13:08:12 +00:00
|
|
|
|
Durian Request: Drivers Recode
Highlights:
* Support for Multi-Target Variables
This was the main reason for this recode. Previously, variables could only be used to give some RNA property used as an input source to the driver a name. However, this meant that effects such as Rotational Difference couldn't be used in conjunction with other effects and/or settings to achieve the powerful results. Now, a variable can take several input targets, perform some interesting operations on them, and spit out a representative value based on that.
* New Variable Types
With the introduction of multi-target variables, there are now 3 types of variable that can be used: single property (i.e. the only type previously), Rotational Difference (angle between two bones), and Distance (distance between two objects or bones).
* New Driver Types
In addition to the existing 'Average', 'Sum', and 'Expression' types, there is now the additional options of 'Minimum' and 'Maximum'. These take the smallest/largest value that one of the variables evaluates to.
* Fix for Driver F-Curve colouring bug
Newly added drivers did not get automatically coloured in the Graph Editor properly. Was caused by inappropriate notifiers being used.
Notes:
* This commit breaks existing 2.5 files with drivers (in other words, they are lost forever).
* Rigify has been corrected to work with the new system. The PyAPI for accessing targets used for the variables could still be made nicer (using subclassing to directly access?), but that is left for later.
* Version patching for 2.49 files still needs to be put back in place.
2010-01-04 21:15:45 +00:00
|
|
|
WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX
|
2009-04-10 13:08:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-11-28 14:37:21 +00:00
|
|
|
void ANIM_OT_driver_button_add (wmOperatorType *ot)
|
2009-04-10 13:08:12 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Add Driver";
|
2009-11-28 14:37:21 +00:00
|
|
|
ot->idname= "ANIM_OT_driver_button_add";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Add driver(s) for the property(s) connected represented by the highlighted button";
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
/* callbacks */
|
|
|
|
ot->exec= add_driver_button_exec;
|
2009-09-25 04:51:04 +00:00
|
|
|
//op->poll= ??? // TODO: need to have some animateable property to do this
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* properties */
|
2009-09-04 07:26:32 +00:00
|
|
|
RNA_def_boolean(ot->srna, "all", 1, "All", "Create drivers for all elements of the array.");
|
2009-04-10 13:08:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove Driver Button Operator ------------------------ */
|
|
|
|
|
|
|
|
static int remove_driver_button_exec (bContext *C, wmOperator *op)
|
|
|
|
{
|
2011-02-13 10:52:18 +00:00
|
|
|
PointerRNA ptr= {{NULL}};
|
2009-04-10 13:08:12 +00:00
|
|
|
PropertyRNA *prop= NULL;
|
|
|
|
short success= 0;
|
2010-04-11 09:13:37 +00:00
|
|
|
int index, all= RNA_boolean_get(op->ptr, "all");
|
2009-04-10 13:08:12 +00:00
|
|
|
|
2009-09-04 11:19:12 +00:00
|
|
|
/* try to find driver using property retrieved from UI */
|
2010-09-25 14:32:26 +00:00
|
|
|
uiContextActiveProperty(C, &ptr, &prop, &index);
|
2010-04-11 09:13:37 +00:00
|
|
|
|
|
|
|
if (all)
|
|
|
|
index= -1;
|
2011-01-14 02:06:35 +00:00
|
|
|
|
2010-09-23 20:26:03 +00:00
|
|
|
if (ptr.id.data && ptr.data && prop) {
|
2011-01-14 02:06:35 +00:00
|
|
|
char *path= get_driver_path_hack(C, &ptr, prop);
|
2010-12-28 05:45:15 +00:00
|
|
|
|
|
|
|
success= ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
|
2010-04-11 09:13:37 +00:00
|
|
|
MEM_freeN(path);
|
2009-04-10 13:08:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
/* send updates */
|
2010-09-25 14:32:26 +00:00
|
|
|
uiContextAnimUpdate(C);
|
2010-12-28 05:45:15 +00:00
|
|
|
|
2010-08-01 12:47:49 +00:00
|
|
|
DAG_ids_flush_update(CTX_data_main(C), 0);
|
2009-04-10 13:08:12 +00:00
|
|
|
|
Durian Request: Drivers Recode
Highlights:
* Support for Multi-Target Variables
This was the main reason for this recode. Previously, variables could only be used to give some RNA property used as an input source to the driver a name. However, this meant that effects such as Rotational Difference couldn't be used in conjunction with other effects and/or settings to achieve the powerful results. Now, a variable can take several input targets, perform some interesting operations on them, and spit out a representative value based on that.
* New Variable Types
With the introduction of multi-target variables, there are now 3 types of variable that can be used: single property (i.e. the only type previously), Rotational Difference (angle between two bones), and Distance (distance between two objects or bones).
* New Driver Types
In addition to the existing 'Average', 'Sum', and 'Expression' types, there is now the additional options of 'Minimum' and 'Maximum'. These take the smallest/largest value that one of the variables evaluates to.
* Fix for Driver F-Curve colouring bug
Newly added drivers did not get automatically coloured in the Graph Editor properly. Was caused by inappropriate notifiers being used.
Notes:
* This commit breaks existing 2.5 files with drivers (in other words, they are lost forever).
* Rigify has been corrected to work with the new system. The PyAPI for accessing targets used for the variables could still be made nicer (using subclassing to directly access?), but that is left for later.
* Version patching for 2.49 files still needs to be put back in place.
2010-01-04 21:15:45 +00:00
|
|
|
WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX
|
2009-04-10 13:08:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-11-28 14:37:21 +00:00
|
|
|
void ANIM_OT_driver_button_remove (wmOperatorType *ot)
|
2009-04-10 13:08:12 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Remove Driver";
|
2009-11-28 14:37:21 +00:00
|
|
|
ot->idname= "ANIM_OT_driver_button_remove";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Remove the driver(s) for the property(s) connected represented by the highlighted button";
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
/* callbacks */
|
|
|
|
ot->exec= remove_driver_button_exec;
|
2009-09-25 04:51:04 +00:00
|
|
|
//op->poll= ??? // TODO: need to have some driver to be able to do this...
|
2009-04-10 13:08:12 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* properties */
|
2009-09-04 07:26:32 +00:00
|
|
|
RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array.");
|
2009-04-10 13:08:12 +00:00
|
|
|
}
|
|
|
|
|
2009-09-25 04:51:04 +00:00
|
|
|
/* Copy Driver Button Operator ------------------------ */
|
|
|
|
|
2010-12-28 05:45:15 +00:00
|
|
|
static int copy_driver_button_exec (bContext *C, wmOperator *op)
|
2009-09-25 04:51:04 +00:00
|
|
|
{
|
2011-02-13 10:52:18 +00:00
|
|
|
PointerRNA ptr= {{NULL}};
|
2009-09-25 04:51:04 +00:00
|
|
|
PropertyRNA *prop= NULL;
|
|
|
|
short success= 0;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
/* try to create driver using property retrieved from UI */
|
2010-09-25 14:32:26 +00:00
|
|
|
uiContextActiveProperty(C, &ptr, &prop, &index);
|
2009-09-25 04:51:04 +00:00
|
|
|
|
2010-09-23 20:26:03 +00:00
|
|
|
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
|
2011-01-14 02:06:35 +00:00
|
|
|
char *path= get_driver_path_hack(C, &ptr, prop);
|
2009-09-25 04:51:04 +00:00
|
|
|
|
|
|
|
if (path) {
|
|
|
|
/* only copy the driver for the button that this was involved for */
|
2010-12-28 05:45:15 +00:00
|
|
|
success= ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0);
|
|
|
|
|
2010-09-25 14:32:26 +00:00
|
|
|
uiContextAnimUpdate(C);
|
2009-09-25 04:51:04 +00:00
|
|
|
|
|
|
|
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";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Copy the driver for the highlighted button";
|
2009-09-25 04:51:04 +00:00
|
|
|
|
|
|
|
/* 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 ------------------------ */
|
|
|
|
|
2010-12-28 05:45:15 +00:00
|
|
|
static int paste_driver_button_exec (bContext *C, wmOperator *op)
|
2009-09-25 04:51:04 +00:00
|
|
|
{
|
2011-02-13 10:52:18 +00:00
|
|
|
PointerRNA ptr= {{NULL}};
|
2009-09-25 04:51:04 +00:00
|
|
|
PropertyRNA *prop= NULL;
|
|
|
|
short success= 0;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
/* try to create driver using property retrieved from UI */
|
2010-09-25 14:32:26 +00:00
|
|
|
uiContextActiveProperty(C, &ptr, &prop, &index);
|
2009-09-25 04:51:04 +00:00
|
|
|
|
2010-09-23 20:26:03 +00:00
|
|
|
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
|
2011-01-14 02:06:35 +00:00
|
|
|
char *path= get_driver_path_hack(C, &ptr, prop);
|
2009-09-25 04:51:04 +00:00
|
|
|
|
|
|
|
if (path) {
|
|
|
|
/* only copy the driver for the button that this was involved for */
|
2010-12-28 05:45:15 +00:00
|
|
|
success= ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
|
|
|
|
|
2010-09-25 14:32:26 +00:00
|
|
|
uiContextAnimUpdate(C);
|
2009-09-25 04:51:04 +00:00
|
|
|
|
|
|
|
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";
|
2010-02-10 21:15:44 +00:00
|
|
|
ot->description= "Paste the driver in the copy/paste buffer for the highlighted button";
|
2009-09-25 04:51:04 +00:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2009-04-10 13:08:12 +00:00
|
|
|
/* ************************************************** */
|