Blender V4.5
drivers.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors, Joshua Leung. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cctype>
10#include <cstdio>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_listbase.h"
16#include "BLI_string.h"
17#include "BLI_utildefines.h"
18
19#include "DNA_anim_types.h"
20
21#include "BKE_anim_data.hh"
22#include "BKE_context.hh"
23#include "BKE_fcurve.hh"
24#include "BKE_fcurve_driver.h"
25#include "BKE_report.hh"
26
27#include "DEG_depsgraph.hh"
29
30#include "ED_keyframing.hh"
31
32#include "UI_interface.hh"
33#include "UI_resources.hh"
34
35#include "WM_api.hh"
36#include "WM_types.hh"
37
38#include "RNA_access.hh"
39#include "RNA_define.hh"
40#include "RNA_path.hh"
41#include "RNA_prototypes.hh"
42
43#include "ANIM_fcurve.hh"
44
45#include "anim_intern.hh"
46
47/* ************************************************** */
48/* Animation Data Validation */
49
51 const char rna_path[],
52 const int array_index,
53 eDriverFCurveCreationMode creation_mode)
54{
55 AnimData *adt;
56 FCurve *fcu;
57
58 /* sanity checks */
59 if (ELEM(nullptr, id, rna_path)) {
60 return nullptr;
61 }
62
63 /* init animdata if none available yet */
64 adt = BKE_animdata_from_id(id);
65 if (adt == nullptr && creation_mode != DRIVER_FCURVE_LOOKUP_ONLY) {
66 adt = BKE_animdata_ensure_id(id);
67 }
68 if (adt == nullptr) {
69 /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */
70 return nullptr;
71 }
72
73 /* try to find f-curve matching for this setting
74 * - add if not found and allowed to add one
75 * TODO: add auto-grouping support? how this works will need to be resolved
76 */
77 fcu = BKE_fcurve_find(&adt->drivers, rna_path, array_index);
78
79 if (fcu == nullptr && creation_mode != DRIVER_FCURVE_LOOKUP_ONLY) {
80 /* use default settings to make a F-Curve */
81 fcu = alloc_driver_fcurve(rna_path, array_index, creation_mode);
82
83 /* just add F-Curve to end of driver list */
84 BLI_addtail(&adt->drivers, fcu);
85 }
86
87 /* return the F-Curve */
88 return fcu;
89}
90
91FCurve *alloc_driver_fcurve(const char rna_path[],
92 const int array_index,
93 eDriverFCurveCreationMode creation_mode)
94{
95 using namespace blender::animrig;
97
99 fcu->auto_smoothing = U.auto_smoothing_new;
100
101 /* store path - make copy, and store that */
102 if (rna_path) {
103 fcu->rna_path = BLI_strdup(rna_path);
104 }
105 fcu->array_index = array_index;
106
107 if (!ELEM(creation_mode, DRIVER_FCURVE_LOOKUP_ONLY, DRIVER_FCURVE_EMPTY)) {
108 /* add some new driver data */
109 fcu->driver = MEM_callocN<ChannelDriver>("ChannelDriver");
110
111 /* F-Modifier or Keyframes? */
112 if (creation_mode == DRIVER_FCURVE_GENERATOR) {
113 /* Python API Backwards compatibility hack:
114 * Create FModifier so that old scripts won't break
115 * for now before 2.7 series -- (September 4, 2013)
116 */
118 }
119 else {
120 /* add 2 keyframes so that user has something to work with
121 * - These are configured to 0,0 and 1,1 to give a 1-1 mapping
122 * which can be easily tweaked from there.
123 */
124 const KeyframeSettings settings = get_keyframe_settings(false);
125 insert_vert_fcurve(fcu, {0.0f, 0.0f}, settings, INSERTKEY_FAST);
126 insert_vert_fcurve(fcu, {1.0f, 1.0f}, settings, INSERTKEY_FAST);
129 }
130 }
131
132 return fcu;
133}
134
135/* ************************************************** */
136/* Driver Management API */
137
138/* Helper for ANIM_add_driver_with_target - Adds the actual driver */
139static int add_driver_with_target(ReportList * /*reports*/,
140 ID *dst_id,
141 const char dst_path[],
142 int dst_index,
143 ID *src_id,
144 const char src_path[],
145 int src_index,
146 PointerRNA *dst_ptr,
147 PropertyRNA *dst_prop,
148 PointerRNA *src_ptr,
149 PropertyRNA *src_prop,
150 short flag,
151 int driver_type)
152{
153 FCurve *fcu;
156 const char *prop_name = RNA_property_identifier(src_prop);
157
158 /* Create F-Curve with Driver */
159 fcu = verify_driver_fcurve(dst_id, dst_path, dst_index, eDriverFCurveCreationMode(add_mode));
160
161 if (fcu && fcu->driver) {
162 ChannelDriver *driver = fcu->driver;
163 DriverVar *dvar;
164
165 /* Set the type of the driver */
166 driver->type = driver_type;
167
168 /* Set driver expression, so that the driver works out of the box
169 *
170 * The following checks define a bit of "auto-detection magic" we use
171 * to ensure that the drivers will behave as expected out of the box
172 * when faced with properties with different units.
173 */
174 /* XXX: if we have N-1 mapping, should we include all those in the expression? */
175 if ((RNA_property_unit(dst_prop) == PROP_UNIT_ROTATION) &&
177 {
178 /* Rotation Destination: normal -> radians, so convert src to radians
179 * (However, if both input and output is a rotation, don't apply such corrections)
180 */
181 STRNCPY(driver->expression, "radians(var)");
182 }
183 else if ((RNA_property_unit(src_prop) == PROP_UNIT_ROTATION) &&
185 {
186 /* Rotation Source: radians -> normal, so convert src to degrees
187 * (However, if both input and output is a rotation, don't apply such corrections)
188 */
189 STRNCPY(driver->expression, "degrees(var)");
190 }
191 else {
192 /* Just a normal property without any unit problems */
193 STRNCPY(driver->expression, "var");
194 }
195
196 /* Create a driver variable for the target
197 * - For transform properties, we want to automatically use "transform channel" instead
198 * (The only issue is with quaternion rotations vs euler channels...)
199 * - To avoid problems with transform properties depending on the final transform that they
200 * control (thus creating pseudo-cycles - see #48734), we don't use transform channels
201 * when both the source and destinations are in same places.
202 */
203 dvar = driver_add_new_variable(driver);
204
205 if (ELEM(src_ptr->type, &RNA_Object, &RNA_PoseBone) &&
206 (STREQ(prop_name, "location") || STREQ(prop_name, "scale") ||
207 STRPREFIX(prop_name, "rotation_")) &&
208 (src_ptr->data != dst_ptr->data))
209 {
210 /* Transform Channel */
211 DriverTarget *dtar;
212
214 dtar = &dvar->targets[0];
215
216 /* Bone or Object target? */
217 dtar->id = src_id;
218 dtar->idtype = GS(src_id->name);
219
220 if (src_ptr->type == &RNA_PoseBone) {
221 RNA_string_get(src_ptr, "name", dtar->pchan_name);
222 }
223
224 /* Transform channel depends on type */
225 if (STREQ(prop_name, "location")) {
226 if (src_index == 2) {
228 }
229 else if (src_index == 1) {
231 }
232 else {
234 }
235 }
236 else if (STREQ(prop_name, "scale")) {
237 if (src_index == 2) {
239 }
240 else if (src_index == 1) {
242 }
243 else {
245 }
246 }
247 else {
248 /* XXX: With quaternions and axis-angle, this mapping might not be correct...
249 * But since those have 4 elements instead, there's not much we can do
250 */
251 if (src_index == 2) {
253 }
254 else if (src_index == 1) {
256 }
257 else {
259 }
260 }
261 }
262 else {
263 /* Single RNA Property */
264 DriverTarget *dtar = &dvar->targets[0];
265
266 /* ID is as-is */
267 dtar->id = src_id;
268 dtar->idtype = GS(src_id->name);
269
270 /* Need to make a copy of the path (or build one with array index built in) */
271 if (RNA_property_array_check(src_prop)) {
272 dtar->rna_path = BLI_sprintfN("%s[%d]", src_path, src_index);
273 }
274 else {
275 dtar->rna_path = BLI_strdup(src_path);
276 }
277 }
278 }
279
280 /* set the done status */
281 return (fcu != nullptr);
282}
283
285 ID *dst_id,
286 const char dst_path[],
287 int dst_index,
288 ID *src_id,
289 const char src_path[],
290 int src_index,
291 short flag,
292 int driver_type,
293 short mapping_type)
294{
296 PropertyRNA *prop;
297
298 PointerRNA ptr2;
299 PropertyRNA *prop2;
300 int done_tot = 0;
301
302 /* validate pointers first - exit if failure */
303 PointerRNA id_ptr = RNA_id_pointer_create(dst_id);
304 if (RNA_path_resolve_property(&id_ptr, dst_path, &ptr, &prop) == false) {
306 reports,
307 RPT_ERROR,
308 "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
309 dst_id->name,
310 dst_path);
311 return 0;
312 }
313
314 PointerRNA id_ptr2 = RNA_id_pointer_create(src_id);
315 if ((RNA_path_resolve_property(&id_ptr2, src_path, &ptr2, &prop2) == false) ||
316 (mapping_type == CREATEDRIVER_MAPPING_NONE))
317 {
318 /* No target - So, fall back to default method for adding a "simple" driver normally */
319 return ANIM_add_driver(
320 reports, dst_id, dst_path, dst_index, flag | CREATEDRIVER_WITH_DEFAULT_DVAR, driver_type);
321 }
322
323 /* handle curve-property mappings based on mapping_type */
324 switch (mapping_type) {
325 /* N-N - Try to match as much as possible, then use the first one. */
327 /* Use the shorter of the two (to avoid out of bounds access) */
328 int dst_len = RNA_property_array_check(prop) ? RNA_property_array_length(&ptr, prop) : 1;
329 int src_len = RNA_property_array_check(prop) ? RNA_property_array_length(&ptr2, prop2) : 1;
330
331 int len = std::min(dst_len, src_len);
332
333 for (int i = 0; i < len; i++) {
335 dst_id,
336 dst_path,
337 i,
338 src_id,
339 src_path,
340 i,
341 &ptr,
342 prop,
343 &ptr2,
344 prop2,
345 flag,
346 driver_type);
347 }
348 break;
349 }
350 /* 1-N - Specified target index for all. */
352 default: {
354
355 for (int i = 0; i < len; i++) {
357 dst_id,
358 dst_path,
359 i,
360 src_id,
361 src_path,
362 src_index,
363 &ptr,
364 prop,
365 &ptr2,
366 prop2,
367 flag,
368 driver_type);
369 }
370 break;
371 }
372
373 /* 1-1 - Use the specified index (unless -1). */
376 dst_id,
377 dst_path,
378 dst_index,
379 src_id,
380 src_path,
381 src_index,
382 &ptr,
383 prop,
384 &ptr2,
385 prop2,
386 flag,
387 driver_type);
388 break;
389 }
390 }
391
392 /* done */
393 return done_tot;
394}
395
396/* --------------------------------- */
397
399 ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
400{
402 PropertyRNA *prop;
403 FCurve *fcu;
404 int array_index_max;
405 int done_tot = 0;
406
407 /* validate pointer first - exit if failure */
409 if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
411 reports,
412 RPT_ERROR,
413 "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
414 id->name,
415 rna_path);
416 return 0;
417 }
418
419 /* key entire array convenience method */
420 if (array_index == -1) {
421 array_index_max = RNA_property_array_length(&ptr, prop);
422 array_index = 0;
423 }
424 else {
425 array_index_max = array_index;
426 }
427
428 /* maximum index should be greater than the start index */
429 if (array_index == array_index_max) {
430 array_index_max += 1;
431 }
432
433 /* will only loop once unless the array index was -1 */
434 for (; array_index < array_index_max; array_index++) {
435 short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1;
436
437 /* create F-Curve with Driver */
438 fcu = verify_driver_fcurve(id, rna_path, array_index, eDriverFCurveCreationMode(add_mode));
439
440 if (fcu && fcu->driver) {
441 ChannelDriver *driver = fcu->driver;
442
443 /* set the type of the driver */
444 driver->type = type;
445
446 /* Creating drivers for buttons will create the driver(s) with type
447 * "scripted expression" so that their values won't be lost immediately,
448 * so here we copy those values over to the driver's expression
449 *
450 * If the "default dvar" option (for easier UI setup of drivers) is provided,
451 * include "var" in the expressions too, so that the user doesn't have to edit
452 * it to get something to happen. It should be fine to just add it to the default
453 * value, so that we get both in the expression, even if it's a bit more confusing
454 * that way...
455 */
456 if (type == DRIVER_TYPE_PYTHON) {
457 PropertyType proptype = RNA_property_type(prop);
458 int array = RNA_property_array_length(&ptr, prop);
459 const char *dvar_prefix = (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) ? "var + " : "";
460 char *expression = driver->expression;
461 const size_t expression_maxncpy = sizeof(driver->expression);
462 int val;
463 float fval;
464
465 if (proptype == PROP_BOOLEAN) {
466 if (!array) {
467 val = RNA_property_boolean_get(&ptr, prop);
468 }
469 else {
470 val = RNA_property_boolean_get_index(&ptr, prop, array_index);
471 }
472
474 expression, expression_maxncpy, "%s%s", dvar_prefix, (val) ? "True" : "False");
475 }
476 else if (proptype == PROP_INT) {
477 if (!array) {
478 val = RNA_property_int_get(&ptr, prop);
479 }
480 else {
481 val = RNA_property_int_get_index(&ptr, prop, array_index);
482 }
483
484 BLI_snprintf(expression, expression_maxncpy, "%s%d", dvar_prefix, val);
485 }
486 else if (proptype == PROP_FLOAT) {
487 if (!array) {
488 fval = RNA_property_float_get(&ptr, prop);
489 }
490 else {
491 fval = RNA_property_float_get_index(&ptr, prop, array_index);
492 }
493
494 BLI_snprintf(expression, expression_maxncpy, "%s%.3f", dvar_prefix, fval);
495 BLI_str_rstrip_float_zero(expression, '\0');
496 }
498 BLI_strncpy(expression, "var", expression_maxncpy);
499 }
500 }
501
502 /* for easier setup of drivers from UI, a driver variable should be
503 * added if flag is set (UI calls only)
504 */
506 /* assume that users will mostly want this to be of type "Transform Channel" too,
507 * since this allows the easiest setting up of common rig components
508 */
509 DriverVar *dvar = driver_add_new_variable(driver);
511 }
512 }
513
514 /* set the done status */
515 done_tot += (fcu != nullptr);
516 }
517
518 /* done */
519 return done_tot;
520}
521
522bool ANIM_remove_driver(ID *id, const char rna_path[], int array_index)
523{
525 if (!adt) {
526 return false;
527 }
528
529 if (array_index >= 0) {
530 /* Simple case: Find the matching driver and remove it. */
531 FCurve *fcu = verify_driver_fcurve(id, rna_path, array_index, DRIVER_FCURVE_LOOKUP_ONLY);
532 if (!fcu) {
533 return false;
534 }
535
536 BLI_remlink(&adt->drivers, fcu);
537 BKE_fcurve_free(fcu);
538 return true;
539 }
540
541 /* Step through all drivers, removing all of those with the same RNA path. */
542 bool any_driver_removed = false;
543 FCurve *fcu_iter = static_cast<FCurve *>(adt->drivers.first);
544 FCurve *fcu;
545 while ((fcu = BKE_fcurve_iter_step(fcu_iter, rna_path)) != nullptr) {
546 /* Store the next fcurve for looping. */
547 fcu_iter = fcu->next;
548
549 BLI_remlink(&adt->drivers, fcu);
550 BKE_fcurve_free(fcu);
551
552 any_driver_removed = true;
553 }
554 return any_driver_removed;
555}
556
557/* ************************************************** */
558/* Driver Management API - Copy/Paste Drivers */
559
560/* Copy/Paste Buffer for Driver Data... */
562
564{
565 /* free the buffer F-Curve if it exists, as if it were just another F-Curve */
568 }
570}
571
573{
574 return (channeldriver_copypaste_buf != nullptr);
575}
576
577/* ------------------- */
578
580 ReportList *reports, ID *id, const char rna_path[], int array_index, short /*flag*/)
581{
583 PropertyRNA *prop;
584 FCurve *fcu;
585
586 /* validate pointer first - exit if failure */
588 if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
590 RPT_ERROR,
591 "Could not find driver to copy, as RNA path is invalid for the given ID (ID = %s, "
592 "path = %s)",
593 id->name,
594 rna_path);
595 return false;
596 }
597
598 /* try to get F-Curve with Driver */
599 fcu = verify_driver_fcurve(id, rna_path, array_index, DRIVER_FCURVE_LOOKUP_ONLY);
600
601 /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */
603
604 /* copy this to the copy/paste buf if it exists */
605 if (fcu && fcu->driver) {
606 /* Make copies of some info such as the rna_path, then clear this info from the
607 * F-Curve temporarily so that we don't end up wasting memory storing the path
608 * which won't get used ever.
609 */
610 char *tmp_path = fcu->rna_path;
611 fcu->rna_path = nullptr;
612
613 /* make a copy of the F-Curve with */
615
616 /* restore the path */
617 fcu->rna_path = tmp_path;
618
619 /* copied... */
620 return true;
621 }
622
623 /* done */
624 return false;
625}
626
628 ReportList *reports, ID *id, const char rna_path[], int array_index, short /*flag*/)
629{
631 PropertyRNA *prop;
632 FCurve *fcu;
633
634 /* validate pointer first - exit if failure */
636 if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop) == false) {
638 reports,
639 RPT_ERROR,
640 "Could not paste driver, as RNA path is invalid for the given ID (ID = %s, path = %s)",
641 id->name,
642 rna_path);
643 return false;
644 }
645
646 /* if the buffer is empty, cannot paste... */
647 if (channeldriver_copypaste_buf == nullptr) {
648 BKE_report(reports, RPT_ERROR, "Paste driver: no driver to paste");
649 return false;
650 }
651
652 /* create Driver F-Curve, but without data which will be copied across... */
653 fcu = verify_driver_fcurve(id, rna_path, array_index, DRIVER_FCURVE_EMPTY);
654
655 if (fcu) {
656 /* copy across the curve data from the buffer curve
657 * NOTE: this step needs care to not miss new settings
658 */
659 /* keyframes/samples */
660 fcu->bezt = static_cast<BezTriple *>(MEM_dupallocN(channeldriver_copypaste_buf->bezt));
661 fcu->fpt = static_cast<FPoint *>(MEM_dupallocN(channeldriver_copypaste_buf->fpt));
662 fcu->totvert = channeldriver_copypaste_buf->totvert;
663
664 /* modifiers */
666
667 /* extrapolation mode */
668 fcu->extend = channeldriver_copypaste_buf->extend;
669
670 /* the 'juicy' stuff - the driver */
672 }
673
674 /* done */
675 return (fcu != nullptr);
676}
677
678/* ************************************************** */
679/* Driver Management API - Copy/Paste Driver Variables */
680
681/* Copy/Paste Buffer for Driver Variables... */
682static ListBase driver_vars_copybuf = {nullptr, nullptr};
683
685{
686 /* Free the driver variables kept in the buffer */
687 if (driver_vars_copybuf.first) {
688 DriverVar *dvar, *dvarn;
689
690 /* Free variables (and any data they use) */
691 for (dvar = static_cast<DriverVar *>(driver_vars_copybuf.first); dvar; dvar = dvarn) {
692 dvarn = dvar->next;
694 }
695 }
696
698}
699
704
705/* -------------------------------------------------- */
706
708{
709 /* sanity checks */
710 if (ELEM(nullptr, fcu, fcu->driver)) {
711 BKE_report(reports, RPT_ERROR, "No driver to copy variables from");
712 return false;
713 }
714
716 BKE_report(reports, RPT_ERROR, "Driver has no variables to copy");
717 return false;
718 }
719
720 /* clear buffer */
722
723 /* copy over the variables */
725
726 return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
727}
728
730{
731 ChannelDriver *driver = (fcu) ? fcu->driver : nullptr;
732 ListBase tmp_list = {nullptr, nullptr};
733
734 /* sanity checks */
736 BKE_report(reports, RPT_ERROR, "No driver variables in the internal clipboard to paste");
737 return false;
738 }
739
740 if (ELEM(nullptr, fcu, fcu->driver)) {
741 BKE_report(reports, RPT_ERROR, "Cannot paste driver variables without a driver");
742 return false;
743 }
744
745 /* 1) Make a new copy of the variables in the buffer - these will get pasted later... */
747
748 /* 2) Prepare destination array */
749 if (replace) {
750 DriverVar *dvar, *dvarn;
751
752 /* Free all existing vars first - We aren't retaining anything */
753 for (dvar = static_cast<DriverVar *>(driver->variables.first); dvar; dvar = dvarn) {
754 dvarn = dvar->next;
755 driver_free_variable_ex(driver, dvar);
756 }
757
759 }
760
761 /* 3) Add new vars */
762 if (driver->variables.last) {
763 DriverVar *last = static_cast<DriverVar *>(driver->variables.last);
764 DriverVar *first = static_cast<DriverVar *>(tmp_list.first);
765
766 last->next = first;
767 first->prev = last;
768
769 driver->variables.last = tmp_list.last;
770 }
771 else {
772 driver->variables.first = tmp_list.first;
773 driver->variables.last = tmp_list.last;
774 }
775
776 /* since driver variables are cached, the expression needs re-compiling too */
777 BKE_driver_invalidate_expression(driver, false, true);
778
779 return true;
780}
781
782/* -------------------------------------------------- */
783
784void ANIM_copy_as_driver(ID *target_id, const char *target_path, const char *var_name)
785{
786 /* Clear copy/paste buffer first (for consistency with other copy/paste buffers). */
789
790 /* Create a dummy driver F-Curve. */
792 ChannelDriver *driver = fcu->driver;
793
794 /* Create a variable. */
795 DriverVar *var = driver_add_new_variable(driver);
796 DriverTarget *target = &var->targets[0];
797
798 target->idtype = GS(target_id->name);
799 target->id = target_id;
800 target->rna_path = BLI_strdup(target_path);
801
802 /* Set the variable name. */
803 if (var_name) {
804 STRNCPY(var->name, var_name);
805
806 /* Sanitize the name. */
807 for (int i = 0; var->name[i]; i++) {
808 if (!(i > 0 ? isalnum(var->name[i]) : isalpha(var->name[i]))) {
809 var->name[i] = '_';
810 }
811 }
812 }
813
814 STRNCPY(driver->expression, var->name);
815
816 /* Store the driver into the copy/paste buffers. */
818
820}
821
822/* ************************************************** */
823/* UI-Button Interface */
824
825/* Add Driver - Enum Defines ------------------------- */
826
828 /* XXX: These names need reviewing. */
830 "SINGLE_MANY",
831 0,
832 "All from Target",
833 "Drive all components of this property using the target picked"},
835 "DIRECT",
836 0,
837 "Single from Target",
838 "Drive this component of this property using the target picked"},
839
841 "MATCH",
842 ICON_COLOR,
843 "Match Indices",
844 "Create drivers for each pair of corresponding elements"},
845
847 "NONE_ALL",
848 ICON_HAND,
849 "Manually Create Later",
850 "Create drivers for all properties without assigning any targets yet"},
852 "NONE_SINGLE",
853 0,
854 "Manually Create Later (Single)",
855 "Create driver for this property only and without assigning any targets yet"},
856 {0, nullptr, 0, nullptr, nullptr},
857};
858
859/* Filtering callback for driver mapping types enum */
861 PointerRNA * /*owner_ptr*/,
862 PropertyRNA * /*owner_prop*/,
863 bool *r_free)
864{
866 EnumPropertyItem *item = nullptr;
867
868 PointerRNA ptr = {};
869 PropertyRNA *prop = nullptr;
870 int index;
871
872 int totitem = 0;
873
874 if (!C) { /* needed for docs */
876 }
877
878 UI_context_active_but_prop_get(C, &ptr, &prop, &index);
879
880 if (ptr.owner_id && ptr.data && prop && RNA_property_driver_editable(&ptr, prop)) {
881 const bool is_array = RNA_property_array_check(prop);
882
883 while (input->identifier) {
884 if (ELEM(input->value, CREATEDRIVER_MAPPING_1_1, CREATEDRIVER_MAPPING_NONE) || (is_array)) {
885 RNA_enum_item_add(&item, &totitem, input);
886 }
887 input++;
888 }
889 }
890 else {
891 /* We need at least this one! */
893 }
894
895 RNA_enum_item_end(&item, &totitem);
896
897 *r_free = true;
898 return item;
899}
900
901/* Add Driver (With Menu) Button Operator ------------------------ */
902
904{
905 PointerRNA ptr = {};
906 PropertyRNA *prop = nullptr;
907 int index;
908 bool driven, special;
909
910 /* this operator can only run if there's a property button active, and it can be animated */
911 UI_context_active_but_prop_get(C, &ptr, &prop, &index);
912
913 if (!(ptr.owner_id && ptr.data && prop)) {
914 return false;
915 }
916 if (!RNA_property_driver_editable(&ptr, prop)) {
917 return false;
918 }
919
920 /* Don't do anything if there is an fcurve for animation without a driver. */
922 C, &ptr, prop, index, nullptr, nullptr, &driven, &special);
923 return (fcu == nullptr || fcu->driver);
924}
925
926/* Wrapper for creating a driver without knowing what the targets will be yet
927 * (i.e. "manual/add later"). */
929{
930 PointerRNA ptr = {};
931 PropertyRNA *prop = nullptr;
932 int index;
933 int success = 0;
934
935 UI_context_active_but_prop_get(C, &ptr, &prop, &index);
936
937 if (mapping_type == CREATEDRIVER_MAPPING_NONE_ALL) {
938 index = -1;
939 }
940
941 if (ptr.owner_id && ptr.data && prop && RNA_property_driver_editable(&ptr, prop)) {
942 short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
943
944 if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
945 success += ANIM_add_driver(
946 op->reports, ptr.owner_id, path->c_str(), index, flags, DRIVER_TYPE_PYTHON);
947 }
948 }
949
950 if (success) {
951 /* send updates */
955
956 return OPERATOR_FINISHED;
957 }
958 return OPERATOR_CANCELLED;
959}
960
962{
963 short mapping_type = RNA_enum_get(op->ptr, "mapping_type");
965 /* Just create driver with no targets */
966 return add_driver_button_none(C, op, mapping_type);
967 }
968
969 /* Create Driver using Eyedropper */
970 wmOperatorType *ot = WM_operatortype_find("UI_OT_eyedropper_driver", true);
971
972 /* XXX: We assume that it's fine to use the same set of properties,
973 * since they're actually the same. */
975
976 return OPERATOR_FINISHED;
977}
978
979/* Show menu or create drivers */
981 wmOperator *op,
982 const wmEvent * /*event*/)
983{
984 PropertyRNA *prop;
985
986 if ((prop = RNA_struct_find_property(op->ptr, "mapping_type")) &&
987 RNA_property_is_set(op->ptr, prop))
988 {
989 /* Mapping Type is Set - Directly go into creating drivers */
990 return add_driver_button_menu_exec(C, op);
991 }
992
993 /* Show menu */
994 /* TODO: This should get filtered by the enum filter. */
995 /* important to execute in the region we're currently in. */
997}
998
1000{
1001 /* identifiers */
1002 ot->name = "Add Driver Menu";
1003 ot->idname = "ANIM_OT_driver_button_add_menu";
1004 ot->description = "Add driver(s) for the property(s) represented by the highlighted button";
1005
1006 /* callbacks */
1009 ot->poll = add_driver_button_poll;
1010
1011 /* flags */
1012 ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1013
1014 /* properties */
1015 ot->prop = RNA_def_enum(ot->srna,
1016 "mapping_type",
1018 0,
1019 "Mapping Type",
1020 "Method used to match target and driven properties");
1022}
1023
1024/* Add Driver Button Operator ------------------------ */
1025
1027 wmOperator *op,
1028 const wmEvent * /*event*/)
1029{
1030 PointerRNA ptr = {};
1031 PropertyRNA *prop = nullptr;
1032 int index;
1033
1034 UI_context_active_but_prop_get(C, &ptr, &prop, &index);
1035
1036 if (ptr.owner_id && ptr.data && prop && RNA_property_driver_editable(&ptr, prop)) {
1037 /* 1) Create a new "empty" driver for this property */
1038 short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
1039 bool changed = false;
1040
1041 if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
1042 changed |=
1044 op->reports, ptr.owner_id, path->c_str(), index, flags, DRIVER_TYPE_PYTHON) != 0);
1045 }
1046
1047 if (changed) {
1048 /* send updates */
1053 }
1054
1055 /* 2) Show editing panel for setting up this driver */
1056 /* TODO: Use a different one from the editing popover, so we can have the single/all toggle? */
1057 UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports);
1058 }
1059
1060 return OPERATOR_INTERFACE;
1061}
1062
1064{
1065 /* identifiers */
1066 ot->name = "Add Driver";
1067 ot->idname = "ANIM_OT_driver_button_add";
1068 ot->description = "Add driver for the property under the cursor";
1069
1070 /* callbacks */
1071 /* NOTE: No exec, as we need all these to use the current context info */
1072 ot->invoke = add_driver_button_invoke;
1073 ot->poll = add_driver_button_poll;
1074
1075 /* flags */
1076 ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1077}
1078
1079/* Remove Driver Button Operator ------------------------ */
1080
1082{
1083 PointerRNA ptr = {};
1084 PropertyRNA *prop = nullptr;
1085 bool changed = false;
1086 int index;
1087 const bool all = RNA_boolean_get(op->ptr, "all");
1088
1089 UI_context_active_but_prop_get(C, &ptr, &prop, &index);
1090
1091 if (all) {
1092 index = -1;
1093 }
1094
1095 if (ptr.owner_id && ptr.data && prop) {
1096 if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
1097 changed = ANIM_remove_driver(ptr.owner_id, path->c_str(), index);
1098 }
1099 }
1100
1101 if (changed) {
1102 /* send updates */
1107 }
1108
1109 return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1110}
1111
1113{
1114 /* identifiers */
1115 ot->name = "Remove Driver";
1116 ot->idname = "ANIM_OT_driver_button_remove";
1117 ot->description =
1118 "Remove the driver(s) for the connected property(s) represented by the highlighted button";
1119
1120 /* callbacks */
1122 /* TODO: `op->poll` need to have some driver to be able to do this. */
1123
1124 /* flags */
1125 ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1126
1127 /* properties */
1128 RNA_def_boolean(ot->srna, "all", true, "All", "Delete drivers for all elements of the array");
1129}
1130
1131/* Edit Driver Button Operator ------------------------ */
1132
1134{
1135 PointerRNA ptr = {};
1136 PropertyRNA *prop = nullptr;
1137 int index;
1138
1139 UI_context_active_but_prop_get(C, &ptr, &prop, &index);
1140
1141 if (ptr.owner_id && ptr.data && prop) {
1142 UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports);
1143 }
1144
1145 return OPERATOR_INTERFACE;
1146}
1147
1149{
1150 /* identifiers */
1151 ot->name = "Edit Driver";
1152 ot->idname = "ANIM_OT_driver_button_edit";
1153 ot->description =
1154 "Edit the drivers for the connected property represented by the highlighted button";
1155
1156 /* callbacks */
1158 /* TODO: `op->poll` need to have some driver to be able to do this. */
1159
1160 /* flags */
1161 ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1162}
1163
1164/* Copy Driver Button Operator ------------------------ */
1165
1167{
1168 PointerRNA ptr = {};
1169 PropertyRNA *prop = nullptr;
1170 bool changed = false;
1171 int index;
1172
1173 UI_context_active_but_prop_get(C, &ptr, &prop, &index);
1174
1175 if (ptr.owner_id && ptr.data && prop && RNA_property_driver_editable(&ptr, prop)) {
1176 if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
1177 /* only copy the driver for the button that this was involved for */
1178 changed = ANIM_copy_driver(op->reports, ptr.owner_id, path->c_str(), index, 0);
1179
1181 }
1182 }
1183
1184 /* Since we're just copying, we don't really need to do anything else. */
1185 return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1186}
1187
1189{
1190 /* identifiers */
1191 ot->name = "Copy Driver";
1192 ot->idname = "ANIM_OT_copy_driver_button";
1193 ot->description = "Copy the driver for the highlighted button";
1194
1195 /* callbacks */
1197 /* TODO: `op->poll` need to have some driver to be able to do this. */
1198
1199 /* flags */
1200 ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1201}
1202
1203/* Paste Driver Button Operator ------------------------ */
1204
1206{
1207 PointerRNA ptr = {};
1208 PropertyRNA *prop = nullptr;
1209 bool changed = false;
1210 int index;
1211
1212 UI_context_active_but_prop_get(C, &ptr, &prop, &index);
1213
1214 if (ptr.owner_id && ptr.data && prop && RNA_property_driver_editable(&ptr, prop)) {
1215 if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
1216 /* only copy the driver for the button that this was involved for */
1217 changed = ANIM_paste_driver(op->reports, ptr.owner_id, path->c_str(), index, 0);
1218
1220
1222
1224
1226 }
1227 }
1228
1229 /* Since we're just copying, we don't really need to do anything else. */
1230 return (changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1231}
1232
1234{
1235 /* identifiers */
1236 ot->name = "Paste Driver";
1237 ot->idname = "ANIM_OT_paste_driver_button";
1238 ot->description = "Paste the driver in the internal clipboard to the highlighted button";
1239
1240 /* callbacks */
1242 /* TODO: `op->poll` need to have some driver to be able to do this. */
1243
1244 /* flags */
1245 ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
1246}
1247
1248/* ************************************************** */
Functions to modify FCurves.
AnimData * BKE_animdata_ensure_id(ID *id)
Definition anim_data.cc:96
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:82
Main * CTX_data_main(const bContext *C)
FCurve * BKE_fcurve_copy(const FCurve *fcu)
FCurve * BKE_fcurve_create()
void copy_fmodifiers(ListBase *dst, const ListBase *src)
void BKE_fcurve_handles_recalc(FCurve *fcu)
FModifier * add_fmodifier(ListBase *modifiers, int type, FCurve *owner_fcu)
FCurve * BKE_fcurve_find_by_rna_context_ui(bContext *C, const PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **r_animdata, bAction **r_action, bool *r_driven, bool *r_special)
FCurve * BKE_fcurve_iter_step(FCurve *fcu_iter, const char rna_path[])
FCurve * BKE_fcurve_find(ListBase *list, const char rna_path[], int array_index)
void BKE_fcurve_free(FCurve *fcu)
struct DriverVar * driver_add_new_variable(struct ChannelDriver *driver)
struct ChannelDriver * fcurve_copy_driver(const struct ChannelDriver *driver)
void BKE_driver_invalidate_expression(struct ChannelDriver *driver, bool expr_changed, bool varname_changed)
void driver_variables_copy(struct ListBase *dst_vars, const struct ListBase *src_vars)
void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar)
void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar)
void driver_change_variable_type(struct DriverVar *dvar, int type)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
int BLI_str_rstrip_float_zero(char *str, char pad) ATTR_NONNULL(1)
Definition string.cc:1002
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define UNUSED_FUNCTION(x)
#define STRPREFIX(a, b)
#define ELEM(...)
#define STREQ(a, b)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1026
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:985
@ DTAR_TRANSCHAN_ROTZ
@ DTAR_TRANSCHAN_SCALEX
@ DTAR_TRANSCHAN_SCALEZ
@ DTAR_TRANSCHAN_LOCX
@ DTAR_TRANSCHAN_LOCY
@ DTAR_TRANSCHAN_ROTX
@ DTAR_TRANSCHAN_LOCZ
@ DTAR_TRANSCHAN_SCALEY
@ DTAR_TRANSCHAN_ROTY
@ DRIVER_TYPE_PYTHON
@ DVAR_TYPE_TRANSFORM_CHAN
@ INSERTKEY_FAST
@ FMODIFIER_TYPE_GENERATOR
@ FCURVE_SELECTED
@ FCURVE_VISIBLE
@ FCURVE_EXTRAPOLATE_LINEAR
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
@ CREATEDRIVER_WITH_FMODIFIER
@ CREATEDRIVER_WITH_DEFAULT_DVAR
@ CREATEDRIVER_MAPPING_NONE_ALL
@ CREATEDRIVER_MAPPING_1_N
@ CREATEDRIVER_MAPPING_NONE
@ CREATEDRIVER_MAPPING_N_N
@ CREATEDRIVER_MAPPING_1_1
eDriverFCurveCreationMode
@ DRIVER_FCURVE_LOOKUP_ONLY
@ DRIVER_FCURVE_KEYFRAMES
@ DRIVER_FCURVE_EMPTY
@ DRIVER_FCURVE_GENERATOR
Read Guarded memory(de)allocation.
PropertyType
Definition RNA_types.hh:149
@ PROP_FLOAT
Definition RNA_types.hh:152
@ PROP_BOOLEAN
Definition RNA_types.hh:150
@ PROP_INT
Definition RNA_types.hh:151
@ PROP_UNIT_ROTATION
Definition RNA_types.hh:166
#define C
Definition RandGen.cpp:29
void UI_context_update_anim_flag(const bContext *C)
wmOperatorStatus UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, ReportList *reports)
uiBut * UI_context_active_but_prop_get(const bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
#define NC_ANIMATION
Definition WM_types.hh:385
#define ND_KEYFRAME_PROP
Definition WM_types.hh:492
ReportList * reports
Definition WM_types.hh:1025
#define ND_FCURVES_ORDER
Definition WM_types.hh:496
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:238
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
#define U
bool ANIM_driver_vars_can_paste()
Definition drivers.cc:700
bool ANIM_copy_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short)
Main Driver Management API calls.
Definition drivers.cc:579
void ANIM_copy_as_driver(ID *target_id, const char *target_path, const char *var_name)
Definition drivers.cc:784
static wmOperatorStatus add_driver_button_menu_exec(bContext *C, wmOperator *op)
Definition drivers.cc:961
void ANIM_OT_driver_button_remove(wmOperatorType *ot)
Definition drivers.cc:1112
void ANIM_OT_driver_button_add(wmOperatorType *ot)
Definition drivers.cc:1063
void ANIM_OT_driver_button_edit(wmOperatorType *ot)
Definition drivers.cc:1148
bool ANIM_driver_can_paste()
Definition drivers.cc:572
static bool add_driver_button_poll(bContext *C)
Definition drivers.cc:903
FCurve * alloc_driver_fcurve(const char rna_path[], const int array_index, eDriverFCurveCreationMode creation_mode)
Definition drivers.cc:91
static wmOperatorStatus add_driver_button_none(bContext *C, wmOperator *op, short mapping_type)
Definition drivers.cc:928
static int add_driver_with_target(ReportList *, 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)
Definition drivers.cc:139
static wmOperatorStatus add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition drivers.cc:1026
bool ANIM_driver_vars_copy(ReportList *reports, FCurve *fcu)
Definition drivers.cc:707
static wmOperatorStatus add_driver_button_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition drivers.cc:980
static wmOperatorStatus copy_driver_button_exec(bContext *C, wmOperator *op)
Definition drivers.cc:1166
int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
Main Driver Management API calls.
Definition drivers.cc:398
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)
Main Driver Management API calls.
Definition drivers.cc:284
bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace)
Definition drivers.cc:729
FCurve * verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, eDriverFCurveCreationMode creation_mode)
Definition drivers.cc:50
static wmOperatorStatus paste_driver_button_exec(bContext *C, wmOperator *op)
Definition drivers.cc:1205
void ANIM_OT_paste_driver_button(wmOperatorType *ot)
Definition drivers.cc:1233
void ANIM_drivers_copybuf_free()
Definition drivers.cc:563
void ANIM_OT_copy_driver_button(wmOperatorType *ot)
Definition drivers.cc:1188
const EnumPropertyItem prop_driver_create_mapping_types[]
Definition drivers.cc:827
static ListBase driver_vars_copybuf
Definition drivers.cc:682
void ANIM_driver_vars_copybuf_free()
Definition drivers.cc:684
static void UNUSED_FUNCTION ANIM_OT_driver_button_add_menu(wmOperatorType *ot)
Definition drivers.cc:999
bool ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short)
Main Driver Management API calls.
Definition drivers.cc:627
static const EnumPropertyItem * driver_mapping_type_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
Definition drivers.cc:860
static wmOperatorStatus edit_driver_button_exec(bContext *C, wmOperator *op)
Definition drivers.cc:1133
static wmOperatorStatus remove_driver_button_exec(bContext *C, wmOperator *op)
Definition drivers.cc:1081
bool ANIM_remove_driver(ID *id, const char rna_path[], int array_index)
Main Driver Management API calls.
Definition drivers.cc:522
static FCurve * channeldriver_copypaste_buf
Definition drivers.cc:561
#define input
bool all(VecOp< bool, D >) RET
#define GS(a)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
KeyframeSettings get_keyframe_settings(bool from_userprefs)
SingleKeyingResult insert_vert_fcurve(FCurve *fcu, const float2 position, const KeyframeSettings &settings, eInsertKeyFlags flag)
Main Key-framing API call.
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_array_check(PropertyRNA *prop)
int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
PropertyUnit RNA_property_unit(PropertyRNA *prop)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
PropertyType RNA_property_type(PropertyRNA *prop)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
bool RNA_property_driver_editable(const PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const char * RNA_property_identifier(const PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
void RNA_enum_items_add_value(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item, int value)
std::optional< std::string > RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition rna_path.cc:1173
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition rna_path.cc:560
ListBase drivers
char expression[256]
char pchan_name[64]
struct DriverVar * next
DriverTarget targets[8]
char name[64]
struct DriverVar * prev
struct FCurve * next
char * rna_path
FPoint * fpt
ChannelDriver * driver
BezTriple * bezt
short extend
int array_index
unsigned int totvert
char auto_smoothing
ListBase modifiers
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
void * last
void * first
StructRNA * type
Definition RNA_types.hh:52
void * data
Definition RNA_types.hh:53
struct ReportList * reports
struct PointerRNA * ptr
i
Definition text_draw.cc:230
uint len
wmOperatorStatus WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4227
wmOperatorType * ot
Definition wm_files.cc:4226
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
wmOperatorStatus WM_menu_invoke_ex(bContext *C, wmOperator *op, wmOperatorCallContext opcontext)
uint8_t flag
Definition wm_window.cc:139