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