PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) { const char *path, *path_full; int index = -1; PYRNA_STRUCT_CHECK_OBJ(self); if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index)) return NULL; if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) == -1) { return NULL; } else { PyObject *ret = NULL; ReportList reports; int result; BKE_reports_init(&reports, RPT_STORE); result = ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, CREATEDRIVER_WITH_FMODIFIER, DRIVER_TYPE_PYTHON); if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) return NULL; if (result) { ID *id = self->ptr.id.data; AnimData *adt = BKE_animdata_from_id(id); FCurve *fcu; PointerRNA tptr; if (index == -1) { /* all, use a list */ int i = 0; ret = PyList_New(0); while ((fcu = list_find_fcurve(&adt->drivers, path_full, i++))) { RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr)); } } else { fcu = list_find_fcurve(&adt->drivers, path_full, index); RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); ret = pyrna_struct_CreatePyObject(&tptr); } WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL); } else { /* XXX, should be handled by reports, */ PyErr_SetString(PyExc_TypeError, "bpy_struct.driver_add(): failed because of an internal error"); return NULL; } MEM_freeN((void *)path_full); return ret; } }
/* helper call for drawing influence/time control curves for a given NLA-strip */ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc) { const float yheight = ymaxc - yminc; /* drawing color is simply a light-gray */ // TODO: is this color suitable? // XXX nasty hacked color for now... which looks quite bad too... glColor3f(0.7f, 0.7f, 0.7f); /* draw with AA'd line */ glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); /* influence -------------------------- */ if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) { FCurve *fcu = list_find_fcurve(&strip->fcurves, "influence", 0); float cfra; /* plot the curve (over the strip's main region) */ glBegin(GL_LINE_STRIP); /* sample at 1 frame intervals, and draw * - min y-val is yminc, max is y-maxc, so clamp in those regions */ for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) { float y = evaluate_fcurve(fcu, cfra); CLAMP(y, 0.0f, 1.0f); glVertex2f(cfra, ((y * yheight) + yminc)); } glEnd(); // GL_LINE_STRIP } else { /* use blend in/out values only if both aren't zero */ if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) { glBegin(GL_LINE_STRIP); /* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */ if (IS_EQF(strip->blendin, 0.0f) == 0) { glVertex2f(strip->start, yminc); glVertex2f(strip->start + strip->blendin, ymaxc); } else glVertex2f(strip->start, ymaxc); /* end of strip */ if (IS_EQF(strip->blendout, 0.0f) == 0) { glVertex2f(strip->end - strip->blendout, ymaxc); glVertex2f(strip->end, yminc); } else glVertex2f(strip->end, ymaxc); glEnd(); // GL_LINE_STRIP } } /* time -------------------------- */ // XXX do we want to draw this curve? in a different color too? /* turn off AA'd lines */ glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); }
static FCurve *rna_Action_fcurve_find(bAction *act, ReportList *reports, const char *data_path, int index) { if (data_path[0] == '\0') { BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument"); return NULL; } /* Returns NULL if not found. */ return list_find_fcurve(&act->curves, data_path, index); }
static FCurve *rna_Driver_find(AnimData *adt, ReportList *reports, const char *data_path, int index) { if (data_path[0] == '\0') { BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument"); return NULL; } /* Returns NULL if not found. */ return list_find_fcurve(&adt->drivers, data_path, index); }
static FCurve *rna_NlaStrip_fcurve_find(NlaStrip *strip, ReportList *reports, const char *data_path, int index) { if (data_path[0] == '\0') { BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument"); return NULL; } /* Returns NULL if not found. */ return list_find_fcurve(&strip->fcurves, data_path, index); }
static FCurve *ui_but_get_fcurve(uiBut *but, bAction **action, int *driven) { FCurve *fcu= NULL; *driven= 0; /* there must be some RNA-pointer + property combo for this button */ if(but->rnaprop && but->rnapoin.id.data && RNA_property_animateable(&but->rnapoin, but->rnaprop)) { AnimData *adt= BKE_animdata_from_id(but->rnapoin.id.data); char *path; if(adt) { if((adt->action && adt->action->curves.first) || (adt->drivers.first)) { /* XXX this function call can become a performance bottleneck */ path= RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop); if(path) { /* animation takes priority over drivers */ if(adt->action && adt->action->curves.first) fcu= list_find_fcurve(&adt->action->curves, path, but->rnaindex); /* if not animated, check if driven */ if(!fcu && (adt->drivers.first)) { fcu= list_find_fcurve(&adt->drivers, path, but->rnaindex); if(fcu) *driven= 1; } if(fcu && action) *action= adt->action; MEM_freeN(path); } } } } return fcu; }
/* 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) { 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_SELECTED); /* store path - make copy, and store that */ fcu->rna_path= BLI_strdupn(rna_path, strlen(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) { /* 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); } /* return the F-Curve */ return fcu; }
/* 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 (with keyframes for visual tweaking), * 2 - add new Driver FCurve (with generator, for script backwards compatibility) * -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) { 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_SELECTED); /* store path - make copy, and store that */ fcu->rna_path = BLI_strdupn(rna_path, strlen(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"); fcu->driver->flag |= DRIVER_FLAG_SHOWDEBUG; /* 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); } 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, INSERTKEY_FAST); insert_vert_fcurve(fcu, 1.0f, 1.0f, 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; }
/* helper call for drawing influence/time control curves for a given NLA-strip */ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos) { const float yheight = ymaxc - yminc; immUniformColor3f(0.7f, 0.7f, 0.7f); /* draw with AA'd line */ GPU_line_smooth(true); GPU_blend(true); /* influence -------------------------- */ if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) { FCurve *fcu = list_find_fcurve(&strip->fcurves, "influence", 0); float cfra; /* plot the curve (over the strip's main region) */ if (fcu) { immBegin(GPU_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1)); /* sample at 1 frame intervals, and draw * - min y-val is yminc, max is y-maxc, so clamp in those regions */ for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) { float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */ CLAMP(y, 0.0f, 1.0f); immVertex2f(pos, cfra, ((y * yheight) + yminc)); } immEnd(); } } else { /* use blend in/out values only if both aren't zero */ if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) { immBeginAtMost(GPU_PRIM_LINE_STRIP, 4); /* start of strip - if no blendin, start straight at 1, * otherwise from 0 to 1 over blendin frames */ if (IS_EQF(strip->blendin, 0.0f) == 0) { immVertex2f(pos, strip->start, yminc); immVertex2f(pos, strip->start + strip->blendin, ymaxc); } else { immVertex2f(pos, strip->start, ymaxc); } /* end of strip */ if (IS_EQF(strip->blendout, 0.0f) == 0) { immVertex2f(pos, strip->end - strip->blendout, ymaxc); immVertex2f(pos, strip->end, yminc); } else { immVertex2f(pos, strip->end, ymaxc); } immEnd(); } } /* turn off AA'd lines */ GPU_line_smooth(false); GPU_blend(false); }