Blender V4.3
fcurve_driver.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 "MEM_guardedalloc.h"
10
11#include "DNA_anim_types.h"
13#include "DNA_object_types.h"
14#include "DNA_scene_types.h"
15
16#include "BLI_alloca.h"
18#include "BLI_listbase.h"
19#include "BLI_math_base_safe.h"
20#include "BLI_math_matrix.h"
21#include "BLI_math_rotation.h"
22#include "BLI_math_vector.h"
23#include "BLI_string_utf8.h"
24#include "BLI_string_utils.hh"
25#include "BLI_threads.h"
26#include "BLI_utildefines.h"
27
28#include "BLT_translation.hh"
29
30#include "BKE_action.hh"
31#include "BKE_animsys.h"
32#include "BKE_armature.hh"
33#include "BKE_constraint.h"
34#include "BKE_fcurve_driver.h"
35#include "BKE_global.hh"
36#include "BKE_object.hh"
37
38#include "RNA_access.hh"
39#include "RNA_path.hh"
40#include "RNA_prototypes.hh"
41
42#include "atomic_ops.h"
43
44#include "CLG_log.h"
45
47
48#ifdef WITH_PYTHON
49# include "BPY_extern.hh"
50#endif
51
52#include <cstring>
53
54#ifdef WITH_PYTHON
55static ThreadMutex python_driver_lock = BLI_MUTEX_INITIALIZER;
56#endif
57
58static CLG_LogRef LOG = {"bke.fcurve"};
59
60/* -------------------------------------------------------------------- */
64/* TypeInfo for Driver Variables (dvti) */
66 /* Evaluation callback. */
67 float (*get_value)(const AnimationEvalContext *anim_eval_context,
68 ChannelDriver *driver,
69 DriverVar *dvar);
70
71 /* Allocation of target slots. */
72 int num_targets; /* Number of target slots required. */
73 const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots. */
74 short target_flags[MAX_DRIVER_TARGETS]; /* Flags defining the requirements for each slot. */
75};
76
77/* Macro to begin definitions */
78#define BEGIN_DVAR_TYPEDEF(type) {
79
80/* Macro to end definitions */
81#define END_DVAR_TYPEDEF }
82
85/* -------------------------------------------------------------------- */
90 const AnimationEvalContext *anim_eval_context)
91{
92 DriverTargetContext driver_target_context;
93
94 driver_target_context.scene = DEG_get_evaluated_scene(anim_eval_context->depsgraph);
95 driver_target_context.view_layer = DEG_get_evaluated_view_layer(anim_eval_context->depsgraph);
96
97 return driver_target_context;
98}
99
100/* Specialized implementation of driver_get_target_property() used for the
101 * DVAR_TYPE_CONTEXT_PROP variable type. */
102static bool driver_get_target_context_property(const DriverTargetContext *driver_target_context,
103 DriverTarget *dtar,
104 PointerRNA *r_property_ptr)
105{
106 switch (dtar->context_property) {
108 *r_property_ptr = RNA_id_pointer_create(&driver_target_context->scene->id);
109 return true;
110
112 *r_property_ptr = RNA_pointer_create(
113 &driver_target_context->scene->id, &RNA_ViewLayer, driver_target_context->view_layer);
114 return true;
115 }
116 }
117
119
120 /* Reset to a nullptr RNA pointer.
121 * This allows to more gracefully handle issues with unsupported configuration (forward
122 * compatibility. for example). */
123 /* TODO(sergey): Replace with utility null-RNA-pointer creation once that is available. */
124 r_property_ptr->data = nullptr;
125 r_property_ptr->type = nullptr;
126 r_property_ptr->owner_id = nullptr;
127
128 return false;
129}
130
131bool driver_get_target_property(const DriverTargetContext *driver_target_context,
132 DriverVar *dvar,
133 DriverTarget *dtar,
134 PointerRNA *r_prop)
135{
136 if (dvar->type == DVAR_TYPE_CONTEXT_PROP) {
137 return driver_get_target_context_property(driver_target_context, dtar, r_prop);
138 }
139
140 if (dtar->id == nullptr) {
141 return false;
142 }
143
144 *r_prop = RNA_id_pointer_create(dtar->id);
145
146 return true;
147}
148
154{
155 if ((dtar->options & DTAR_OPTION_USE_FALLBACK) == 0) {
156 return false;
157 }
158
159 dtar->flag &= ~DTAR_FLAG_INVALID;
161 return true;
162}
163
168static float dtar_get_prop_val(const AnimationEvalContext *anim_eval_context,
169 ChannelDriver *driver,
170 DriverVar *dvar,
171 DriverTarget *dtar)
172{
173 /* Sanity check. */
174 if (driver == nullptr) {
175 return 0.0f;
176 }
177
178 dtar->flag &= ~DTAR_FLAG_FALLBACK_USED;
179
180 /* Get property to resolve the target from.
181 * Naming is a bit confusing, but this is what is exposed as "Prop" or "Context Property" in
182 * interface. */
184 anim_eval_context);
185 PointerRNA property_ptr;
186 if (!driver_get_target_property(&driver_target_context, dvar, dtar, &property_ptr)) {
187 if (G.debug & G_DEBUG) {
188 CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path);
189 }
190
191 driver->flag |= DRIVER_FLAG_INVALID;
192 dtar->flag |= DTAR_FLAG_INVALID;
193 return 0.0f;
194 }
195
196 /* Get property to read from, and get value as appropriate. */
197 PointerRNA value_ptr;
198 PropertyRNA *value_prop;
199 int index = -1;
200 float value = 0.0f;
202 &property_ptr, dtar->rna_path, &value_ptr, &value_prop, &index))
203 {
204 if (dtar_try_use_fallback(dtar)) {
205 return dtar->fallback_value;
206 }
207
208 /* Path couldn't be resolved. */
209 if (G.debug & G_DEBUG) {
211 "Driver Evaluation Error: cannot resolve target for %s -> %s",
212 property_ptr.owner_id->name,
213 dtar->rna_path);
214 }
215
216 driver->flag |= DRIVER_FLAG_INVALID;
217 dtar->flag |= DTAR_FLAG_INVALID;
218 return 0.0f;
219 }
220
221 if (RNA_property_array_check(value_prop)) {
222 /* Array. */
223 if (index < 0 || index >= RNA_property_array_length(&value_ptr, value_prop)) {
224 if (dtar_try_use_fallback(dtar)) {
225 return dtar->fallback_value;
226 }
227
228 /* Out of bounds. */
229 if (G.debug & G_DEBUG) {
231 "Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)",
232 property_ptr.owner_id->name,
233 dtar->rna_path,
234 index);
235 }
236
237 driver->flag |= DRIVER_FLAG_INVALID;
238 dtar->flag |= DTAR_FLAG_INVALID;
239 return 0.0f;
240 }
241
242 switch (RNA_property_type(value_prop)) {
243 case PROP_BOOLEAN:
244 value = float(RNA_property_boolean_get_index(&value_ptr, value_prop, index));
245 break;
246 case PROP_INT:
247 value = float(RNA_property_int_get_index(&value_ptr, value_prop, index));
248 break;
249 case PROP_FLOAT:
250 value = RNA_property_float_get_index(&value_ptr, value_prop, index);
251 break;
252 default:
253 break;
254 }
255 }
256 else {
257 /* Not an array. */
258 switch (RNA_property_type(value_prop)) {
259 case PROP_BOOLEAN:
260 value = float(RNA_property_boolean_get(&value_ptr, value_prop));
261 break;
262 case PROP_INT:
263 value = float(RNA_property_int_get(&value_ptr, value_prop));
264 break;
265 case PROP_FLOAT:
266 value = RNA_property_float_get(&value_ptr, value_prop);
267 break;
268 case PROP_ENUM:
269 value = float(RNA_property_enum_get(&value_ptr, value_prop));
270 break;
271 default:
272 break;
273 }
274 }
275
276 /* If we're still here, we should be ok. */
277 dtar->flag &= ~DTAR_FLAG_INVALID;
278 return value;
279}
280
282 const AnimationEvalContext *anim_eval_context,
283 ChannelDriver *driver,
284 DriverVar *dvar,
285 DriverTarget *dtar,
286 const bool allow_no_index,
287 PointerRNA *r_ptr,
288 PropertyRNA **r_prop,
289 int *r_index)
290{
292 PropertyRNA *prop;
293 int index = -1;
294
295 /* Sanity check. */
296 if (ELEM(nullptr, driver, dtar)) {
298 }
299
300 dtar->flag &= ~DTAR_FLAG_FALLBACK_USED;
301
302 /* Get RNA-pointer for the data-block given in target. */
304 anim_eval_context);
305 PointerRNA target_ptr;
306 if (!driver_get_target_property(&driver_target_context, dvar, dtar, &target_ptr)) {
307 if (G.debug & G_DEBUG) {
308 CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path);
309 }
310
311 driver->flag |= DRIVER_FLAG_INVALID;
312 dtar->flag |= DTAR_FLAG_INVALID;
314 }
315
316 /* Get property to read from, and get value as appropriate. */
317 if (dtar->rna_path == nullptr || dtar->rna_path[0] == '\0') {
319 prop = nullptr; /* OK. */
320 }
321 else if (RNA_path_resolve_full(&target_ptr, dtar->rna_path, &ptr, &prop, &index)) {
322 /* OK. */
323 }
324 else {
325 if (dtar_try_use_fallback(dtar)) {
327 *r_prop = nullptr;
328 *r_index = -1;
330 }
331
332 /* Path couldn't be resolved. */
333 if (G.debug & G_DEBUG) {
335 "Driver Evaluation Error: cannot resolve target for %s -> %s",
336 target_ptr.owner_id->name,
337 dtar->rna_path);
338 }
339
341 *r_prop = nullptr;
342 *r_index = -1;
343
344 driver->flag |= DRIVER_FLAG_INVALID;
345 dtar->flag |= DTAR_FLAG_INVALID;
347 }
348
349 *r_ptr = ptr;
350 *r_prop = prop;
351 *r_index = index;
352
353 /* Verify the array index and apply fallback if appropriate. */
354 if (prop && RNA_property_array_check(prop)) {
355 if ((index < 0 && !allow_no_index) || index >= RNA_property_array_length(&ptr, prop)) {
356 if (dtar_try_use_fallback(dtar)) {
358 }
359
360 /* Out of bounds. */
361 if (G.debug & G_DEBUG) {
363 "Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)",
365 dtar->rna_path,
366 index);
367 }
368
369 driver->flag |= DRIVER_FLAG_INVALID;
370 dtar->flag |= DTAR_FLAG_INVALID;
372 }
373 }
374
375 /* If we're still here, we should be ok. */
376 dtar->flag &= ~DTAR_FLAG_INVALID;
378}
379
381{
382 short valid_targets = 0;
383
385 Object *ob = (Object *)dtar->id;
386
387 /* Check if this target has valid data. */
388 if ((ob == nullptr) || (GS(ob->id.name) != ID_OB)) {
389 /* Invalid target, so will not have enough targets. */
390 driver->flag |= DRIVER_FLAG_INVALID;
391 dtar->flag |= DTAR_FLAG_INVALID;
392 }
393 else {
394 /* Target seems to be OK now. */
395 dtar->flag &= ~DTAR_FLAG_INVALID;
396 valid_targets++;
397 }
398 }
400
401 return valid_targets;
402}
403
406/* -------------------------------------------------------------------- */
410/* Evaluate 'single prop' driver variable. */
411static float dvar_eval_singleProp(const AnimationEvalContext *anim_eval_context,
412 ChannelDriver *driver,
413 DriverVar *dvar)
414{
415 /* Just evaluate the first target slot. */
416 return dtar_get_prop_val(anim_eval_context, driver, dvar, &dvar->targets[0]);
417}
418
419/* Evaluate 'rotation difference' driver variable. */
420static float dvar_eval_rotDiff(const AnimationEvalContext * /*anim_eval_context*/,
421 ChannelDriver *driver,
422 DriverVar *dvar)
423{
424 short valid_targets = driver_check_valid_targets(driver, dvar);
425
426 /* Make sure we have enough valid targets to use - all or nothing for now. */
427 if (driver_check_valid_targets(driver, dvar) != 2) {
428 if (G.debug & G_DEBUG) {
429 CLOG_WARN(&LOG,
430 "RotDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)",
431 valid_targets,
432 dvar->targets[0].id,
433 dvar->targets[1].id);
434 }
435 return 0.0f;
436 }
437
438 const float(*mat[2])[4];
439
440 /* NOTE: for now, these are all just world-space. */
441 for (int i = 0; i < 2; i++) {
442 /* Get pointer to loc values to store in. */
443 DriverTarget *dtar = &dvar->targets[i];
444 Object *ob = (Object *)dtar->id;
445 bPoseChannel *pchan;
446
447 /* After the checks above, the targets should be valid here. */
448 BLI_assert((ob != nullptr) && (GS(ob->id.name) == ID_OB));
449
450 /* Try to get pose-channel. */
451 pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
452
453 /* Check if object or bone. */
454 if (pchan) {
455 /* Bone. */
456 mat[i] = pchan->pose_mat;
457 }
458 else {
459 /* Object. */
460 mat[i] = ob->object_to_world().ptr();
461 }
462 }
463
464 float q1[4], q2[4], quat[4], angle;
465
466 /* Use the final posed locations. */
467 mat4_to_quat(q1, mat[0]);
468 mat4_to_quat(q2, mat[1]);
469
471 mul_qt_qtqt(quat, q1, q2);
472 angle = 2.0f * safe_acosf(quat[0]);
473 angle = fabsf(angle);
474
475 return (angle > float(M_PI)) ? float((2.0f * float(M_PI)) - angle) : float(angle);
476}
477
483static float dvar_eval_locDiff(const AnimationEvalContext * /*anim_eval_context*/,
484 ChannelDriver *driver,
485 DriverVar *dvar)
486{
487 float loc1[3] = {0.0f, 0.0f, 0.0f};
488 float loc2[3] = {0.0f, 0.0f, 0.0f};
489 short valid_targets = driver_check_valid_targets(driver, dvar);
490
491 /* Make sure we have enough valid targets to use - all or nothing for now. */
492 if (valid_targets < dvar->num_targets) {
493 if (G.debug & G_DEBUG) {
494 CLOG_WARN(&LOG,
495 "LocDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)",
496 valid_targets,
497 dvar->targets[0].id,
498 dvar->targets[1].id);
499 }
500 return 0.0f;
501 }
502
503 /* SECOND PASS: get two location values */
504 /* NOTE: for now, these are all just world-space */
506 /* Get pointer to loc values to store in. */
507 Object *ob = (Object *)dtar->id;
508 bPoseChannel *pchan;
509 float tmp_loc[3];
510
511 /* After the checks above, the targets should be valid here. */
512 BLI_assert((ob != nullptr) && (GS(ob->id.name) == ID_OB));
513
514 /* Try to get pose-channel. */
515 pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
516
517 /* Check if object or bone. */
518 if (pchan) {
519 /* Bone. */
520 if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
521 if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
522 float mat[4][4];
523
524 /* Extract transform just like how the constraints do it! */
525 copy_m4_m4(mat, pchan->pose_mat);
527 ob, pchan, nullptr, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false);
528
529 /* ... and from that, we get our transform. */
530 copy_v3_v3(tmp_loc, mat[3]);
531 }
532 else {
533 /* Transform space (use transform values directly). */
534 copy_v3_v3(tmp_loc, pchan->loc);
535 }
536 }
537 else {
538 /* Convert to world-space. */
539 copy_v3_v3(tmp_loc, pchan->pose_head);
540 mul_m4_v3(ob->object_to_world().ptr(), tmp_loc);
541 }
542 }
543 else {
544 /* Object. */
545 if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
546 if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
547 /* XXX: this should practically be the same as transform space. */
548 float mat[4][4];
549
550 /* Extract transform just like how the constraints do it! */
551 copy_m4_m4(mat, ob->object_to_world().ptr());
553 ob, nullptr, nullptr, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false);
554
555 /* ... and from that, we get our transform. */
556 copy_v3_v3(tmp_loc, mat[3]);
557 }
558 else {
559 /* Transform space (use transform values directly). */
560 copy_v3_v3(tmp_loc, ob->loc);
561 }
562 }
563 else {
564 /* World-space. */
565 copy_v3_v3(tmp_loc, ob->object_to_world().location());
566 }
567 }
568
569 /* Copy the location to the right place. */
570 if (tarIndex) {
571 copy_v3_v3(loc2, tmp_loc);
572 }
573 else {
574 copy_v3_v3(loc1, tmp_loc);
575 }
576 }
578
579 /* If we're still here, there should now be two targets to use,
580 * so just take the length of the vector between these points. */
581 return len_v3v3(loc1, loc2);
582}
583
587static float dvar_eval_transChan(const AnimationEvalContext * /*anim_eval_context*/,
588 ChannelDriver *driver,
589 DriverVar *dvar)
590{
591 DriverTarget *dtar = &dvar->targets[0];
592 Object *ob = (Object *)dtar->id;
593 bPoseChannel *pchan;
594 float mat[4][4];
595 float oldEul[3] = {0.0f, 0.0f, 0.0f};
596 bool use_eulers = false;
597 short rot_order = ROT_MODE_EUL;
598
599 /* Check if this target has valid data. */
600 if ((ob == nullptr) || (GS(ob->id.name) != ID_OB)) {
601 /* Invalid target, so will not have enough targets. */
602 driver->flag |= DRIVER_FLAG_INVALID;
603 dtar->flag |= DTAR_FLAG_INVALID;
604 return 0.0f;
605 }
606
607 /* Try to get pose-channel. */
608 pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
609 if (dtar->pchan_name[0] != '\0' && !pchan) {
610 driver->flag |= DRIVER_FLAG_INVALID;
611 dtar->flag |= DTAR_FLAG_INVALID;
612 return 0.0f;
613 }
614
615 /* Target should be valid now. */
616 dtar->flag &= ~DTAR_FLAG_INVALID;
617
618 /* Check if object or bone, and get transform matrix accordingly:
619 * - "use_eulers" code is used to prevent the problems associated with non-uniqueness
620 * of euler decomposition from matrices #20870.
621 * - "local-space" is for #21384, where parent results are not wanted
622 * but #DTAR_FLAG_LOCAL_CONSTS is for all the common "corrective-shapes-for-limbs" situations.
623 */
624 if (pchan) {
625 /* Bone. */
626 if (pchan->rotmode > 0) {
627 copy_v3_v3(oldEul, pchan->eul);
628 rot_order = pchan->rotmode;
629 use_eulers = true;
630 }
631
632 if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
633 if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
634 /* Just like how the constraints do it! */
635 copy_m4_m4(mat, pchan->pose_mat);
637 ob, pchan, nullptr, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false);
638 }
639 else {
640 /* Specially calculate local matrix, since chan_mat is not valid
641 * since it stores delta transform of pose_mat so that deforms work
642 * so it cannot be used here for "transform" space. */
643 BKE_pchan_to_mat4(pchan, mat);
644 }
645 }
646 else {
647 /* World-space matrix. */
648 mul_m4_m4m4(mat, ob->object_to_world().ptr(), pchan->pose_mat);
649 }
650 }
651 else {
652 /* Object. */
653 if (ob->rotmode > 0) {
654 copy_v3_v3(oldEul, ob->rot);
655 rot_order = ob->rotmode;
656 use_eulers = true;
657 }
658
659 if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
660 if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
661 /* Just like how the constraints do it! */
662 copy_m4_m4(mat, ob->object_to_world().ptr());
664 ob, nullptr, nullptr, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false);
665 }
666 else {
667 /* Transforms to matrix. */
668 BKE_object_to_mat4(ob, mat);
669 }
670 }
671 else {
672 /* World-space matrix - just the good-old one. */
673 copy_m4_m4(mat, ob->object_to_world().ptr());
674 }
675 }
676
677 /* Check which transform. */
678 if (dtar->transChan >= MAX_DTAR_TRANSCHAN_TYPES) {
679 /* Not valid channel. */
680 return 0.0f;
681 }
682 if (dtar->transChan == DTAR_TRANSCHAN_SCALE_AVG) {
683 /* Cubic root of the change in volume, equal to the geometric mean
684 * of scale over all three axes unless the matrix includes shear. */
685 return cbrtf(mat4_to_volume_scale(mat));
686 }
688 /* Extract scale, and choose the right axis,
689 * inline 'mat4_to_size'. */
690 return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]);
691 }
692 if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) {
693 /* Extract rotation as eulers (if needed)
694 * - definitely if rotation order isn't eulers already
695 * - if eulers, then we have 2 options:
696 * a) decompose transform matrix as required, then try to make eulers from
697 * there compatible with original values
698 * b) [NOT USED] directly use the original values (no decomposition)
699 * - only an option for "transform space", if quality is really bad with a)
700 */
701 float quat[4];
702 int channel;
703
704 if (dtar->transChan == DTAR_TRANSCHAN_ROTW) {
705 channel = 0;
706 }
707 else {
708 channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX;
709 BLI_assert(channel < 4);
710 }
711
713 mat, rot_order, dtar->rotation_mode, channel, false, quat);
714
715 if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) {
716 compatible_eul(quat + 1, oldEul);
717 }
718
719 return quat[channel];
720 }
721
722 /* Extract location and choose right axis. */
723 return mat[3][dtar->transChan];
724}
725
726/* Evaluate 'context prop' driver variable. */
727static float dvar_eval_contextProp(const AnimationEvalContext *anim_eval_context,
728 ChannelDriver *driver,
729 DriverVar *dvar)
730{
731 /* Just evaluate the first target slot. */
732 return dtar_get_prop_val(anim_eval_context, driver, dvar, &dvar->targets[0]);
733}
734
735/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */
736static void quaternion_to_angles(float quat[4], int channel)
737{
738 if (channel < 0) {
739 quat[0] = 2.0f * safe_acosf(quat[0]);
740
741 for (int i = 1; i < 4; i++) {
742 quat[i] = 2.0f * safe_asinf(quat[i]);
743 }
744 }
745 else if (channel == 0) {
746 quat[0] = 2.0f * safe_acosf(quat[0]);
747 }
748 else {
749 quat[channel] = 2.0f * safe_asinf(quat[channel]);
750 }
751}
752
754 float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4])
755{
756 float *const quat = r_buf;
757 float *const eul = r_buf + 1;
758
759 zero_v4(r_buf);
760
761 if (rotation_mode == DTAR_ROTMODE_AUTO) {
762 mat4_to_eulO(eul, auto_order, mat);
763 }
764 else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) {
765 mat4_to_eulO(eul, rotation_mode, mat);
766 }
767 else if (rotation_mode == DTAR_ROTMODE_QUATERNION) {
768 mat4_to_quat(quat, mat);
769
770 /* For Transformation constraint convenience, convert to pseudo-angles. */
771 if (angles) {
772 quaternion_to_angles(quat, channel);
773 }
774 }
775 else if (rotation_mode >= DTAR_ROTMODE_SWING_TWIST_X &&
776 rotation_mode <= DTAR_ROTMODE_SWING_TWIST_Z)
777 {
778 int axis = rotation_mode - DTAR_ROTMODE_SWING_TWIST_X;
779 float raw_quat[4], twist;
780
781 mat4_to_quat(raw_quat, mat);
782
783 if (channel == axis + 1) {
784 /* If only the twist angle is needed, skip computing swing. */
785 twist = quat_split_swing_and_twist(raw_quat, axis, nullptr, nullptr);
786 }
787 else {
788 twist = quat_split_swing_and_twist(raw_quat, axis, quat, nullptr);
789
790 quaternion_to_angles(quat, channel);
791 }
792
793 quat[axis + 1] = twist;
794 }
795 else {
796 BLI_assert(false);
797 }
798}
799
802/* -------------------------------------------------------------------- */
806/* Table of Driver Variable Type Info Data */
809 1, /* Number of targets used. */
810 {"Property"}, /* UI names for targets */
811 {0} /* Flags. */
813
815 2, /* Number of targets used. */
816 {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */
820
822 2, /* Number of targets used. */
823 {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */
827
829 1, /* Number of targets used. */
830 {"Object/Bone"}, /* UI names for targets */
833
835 1, /* Number of targets used. */
836 {"Property"}, /* UI names for targets */
837 {0} /* Flags. */
839};
840
841/* Get driver variable typeinfo */
843{
844 /* Check if valid type. */
845 if ((type >= 0) && (type < MAX_DVAR_TYPES)) {
846 return &dvar_types[type];
847 }
848
849 return nullptr;
850}
851
854/* -------------------------------------------------------------------- */
859{
860 /* Sanity checks. */
861 if (dvar == nullptr) {
862 return;
863 }
864
865 /* Free target vars:
866 * - need to go over all of them, not just up to the ones that are used
867 * currently, since there may be some lingering RNA paths from
868 * previous users needing freeing
869 */
871 /* Free RNA path if applicable. */
872 if (dtar->rna_path) {
873 MEM_freeN(dtar->rna_path);
874 }
875 }
877
878 /* Remove the variable from the driver. */
879 BLI_freelinkN(variables, dvar);
880}
881
883{
884 /* Remove and free the driver variable. */
885 driver_free_variable(&driver->variables, dvar);
886
887 /* Since driver variables are cached, the expression needs re-compiling too. */
888 BKE_driver_invalidate_expression(driver, false, true);
889}
890
891void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars)
892{
894 BLI_duplicatelist(dst_vars, src_vars);
895
896 LISTBASE_FOREACH (DriverVar *, dvar, dst_vars) {
897 /* Need to go over all targets so that we don't leave any dangling paths. */
899 /* Make a copy of target's rna path if available. */
900 if (dtar->rna_path) {
901 dtar->rna_path = static_cast<char *>(MEM_dupallocN(dtar->rna_path));
902 }
903 }
905 }
906}
907
909{
910 const DriverVarTypeInfo *dvti = get_dvar_typeinfo(type);
911
912 /* Sanity check. */
913 if (ELEM(nullptr, dvar, dvti)) {
914 return;
915 }
916
917 /* Set the new settings. */
918 dvar->type = type;
919 dvar->num_targets = dvti->num_targets;
920
921 /* Make changes to the targets based on the defines for these types.
922 * NOTE: only need to make sure the ones we're using here are valid. */
924 short flags = dvti->target_flags[tarIndex];
925
926 /* Store the flags. */
927 dtar->flag = flags;
928
929 /* Object ID types only, or idtype not yet initialized. */
930 if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0)) {
931 dtar->idtype = ID_OB;
932 }
933 }
935}
936
938{
939 /* Special character blacklist */
940 const char special_char_blacklist[] = {
941 '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '+', '=', '-', '/', '\\',
942 '?', ':', ';', '<', '>', '{', '}', '[', ']', '|', ' ', '.', '\t', '\n', '\r',
943 };
944
945 /* Sanity checks. */
946 if (dvar == nullptr) {
947 return;
948 }
949
950 /* Clear all invalid-name flags. */
951 dvar->flag &= ~DVAR_ALL_INVALID_FLAGS;
952
953 /* 0) Zero-length identifiers are not allowed */
954 if (dvar->name[0] == '\0') {
956 }
957
958 /* 1) Must start with a letter */
959 /* XXX: We assume that valid unicode letters in other languages are ok too,
960 * hence the blacklisting. */
961 if (IN_RANGE_INCL(dvar->name[0], '0', '9')) {
963 }
964 else if (dvar->name[0] == '_') {
965 /* NOTE: We don't allow names to start with underscores
966 * (i.e. it helps when ruling out security risks) */
968 }
969
970 /* 2) Must not contain invalid stuff in the middle of the string */
971 if (strchr(dvar->name, ' ')) {
973 }
974 if (strchr(dvar->name, '.')) {
976 }
977
978 /* 3) Check for special characters - Either at start, or in the middle */
979 for (int i = 0; i < sizeof(special_char_blacklist); i++) {
980 char *match = strchr(dvar->name, special_char_blacklist[i]);
981
982 if (match == dvar->name) {
984 }
985 else if (match != nullptr) {
987 }
988 }
989
990/* 4) Check if the name is a reserved keyword
991 * NOTE: These won't confuse Python, but it will be impossible to use the variable
992 * in an expression without Python misinterpreting what these are for
993 */
994#ifdef WITH_PYTHON
995 if (BPY_string_is_keyword(dvar->name)) {
997 }
998#endif
999
1000 /* If any these conditions match, the name is invalid */
1001 if (dvar->flag & DVAR_ALL_INVALID_FLAGS) {
1003 }
1004}
1005
1007{
1008 ListBase variables = BLI_listbase_from_link((Link *)dvar);
1009 BLI_uniquename(&variables, dvar, dvar->name, '_', offsetof(DriverVar, name), sizeof(dvar->name));
1010}
1011
1013{
1014 DriverVar *dvar;
1015
1016 /* Sanity checks. */
1017 if (driver == nullptr) {
1018 return nullptr;
1019 }
1020
1021 /* Make a new variable. */
1022 dvar = static_cast<DriverVar *>(MEM_callocN(sizeof(DriverVar), "DriverVar"));
1023 BLI_addtail(&driver->variables, dvar);
1024
1025 /* Give the variable a 'unique' name. */
1027 BLI_uniquename(&driver->variables,
1028 dvar,
1030 '_',
1031 offsetof(DriverVar, name),
1032 sizeof(dvar->name));
1033
1034 /* Set the default type to 'single prop'. */
1036
1037 /* Since driver variables are cached, the expression needs re-compiling too. */
1038 BKE_driver_invalidate_expression(driver, false, true);
1039
1040 /* Return the target. */
1041 return dvar;
1042}
1043
1045{
1046 ChannelDriver *driver;
1047 DriverVar *dvar, *dvarn;
1048
1049 /* Sanity checks. */
1050 if (ELEM(nullptr, fcu, fcu->driver)) {
1051 return;
1052 }
1053 driver = fcu->driver;
1054
1055 /* Free driver targets. */
1056 for (dvar = static_cast<DriverVar *>(driver->variables.first); dvar; dvar = dvarn) {
1057 dvarn = dvar->next;
1058 driver_free_variable_ex(driver, dvar);
1059 }
1060
1061#ifdef WITH_PYTHON
1062 /* Free compiled driver expression. */
1063 if (driver->expr_comp) {
1064 BPY_DECREF(driver->expr_comp);
1065 }
1066#endif
1067
1069
1070 /* Free driver itself, then set F-Curve's point to this to nullptr
1071 * (as the curve may still be used). */
1072 MEM_freeN(driver);
1073 fcu->driver = nullptr;
1074}
1075
1077{
1078 ChannelDriver *ndriver;
1079
1080 /* Sanity checks. */
1081 if (driver == nullptr) {
1082 return nullptr;
1083 }
1084
1085 /* Copy all data. */
1086 ndriver = static_cast<ChannelDriver *>(MEM_dupallocN(driver));
1087 ndriver->expr_comp = nullptr;
1088 ndriver->expr_simple = nullptr;
1089
1090 /* Copy variables. */
1091
1092 /* To get rid of refs to non-copied data (that's still used on original). */
1093 BLI_listbase_clear(&ndriver->variables);
1094 driver_variables_copy(&ndriver->variables, &driver->variables);
1095
1096 /* Return the new driver. */
1097 return ndriver;
1098}
1099
1102/* -------------------------------------------------------------------- */
1106/* Index constants for the expression parameter array. */
1107enum {
1108 /* Index of the 'frame' variable. */
1110 /* Index of the first user-defined driver variable. */
1113
1115{
1116 /* Prepare parameter names. */
1117 int names_len = BLI_listbase_count(&driver->variables);
1118 const char **names = static_cast<const char **>(
1119 BLI_array_alloca(names, names_len + VAR_INDEX_CUSTOM));
1120 int i = VAR_INDEX_CUSTOM;
1121
1122 names[VAR_INDEX_FRAME] = "frame";
1123
1124 LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
1125 names[i++] = dvar->name;
1126 }
1127
1128 return BLI_expr_pylike_parse(driver->expression, names, names_len + VAR_INDEX_CUSTOM);
1129}
1130
1132{
1133 /* Check if the 'frame' parameter is actually used. */
1135}
1136
1137static bool driver_evaluate_simple_expr(const AnimationEvalContext *anim_eval_context,
1138 ChannelDriver *driver,
1139 ExprPyLike_Parsed *expr,
1140 float *result,
1141 float time)
1142{
1143 /* Prepare parameter values. */
1144 int vars_len = BLI_listbase_count(&driver->variables);
1145 double *vars = static_cast<double *>(BLI_array_alloca(vars, vars_len + VAR_INDEX_CUSTOM));
1146 int i = VAR_INDEX_CUSTOM;
1147
1148 vars[VAR_INDEX_FRAME] = time;
1149
1150 LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
1151 vars[i++] = driver_get_variable_value(anim_eval_context, driver, dvar);
1152 }
1153
1154 /* Evaluate expression. */
1155 double result_val;
1157 expr, vars, vars_len + VAR_INDEX_CUSTOM, &result_val);
1158 const char *message;
1159
1160 switch (status) {
1162 if (isfinite(result_val)) {
1163 *result = float(result_val);
1164 }
1165 return true;
1166
1169 message = (status == EXPR_PYLIKE_DIV_BY_ZERO) ? "Division by Zero" : "Math Domain Error";
1170 CLOG_ERROR(&LOG, "%s in Driver: '%s'", message, driver->expression);
1171
1172 driver->flag |= DRIVER_FLAG_INVALID;
1173 return true;
1174
1175 default:
1176 /* Arriving here means a bug, not user error. */
1177 CLOG_ERROR(&LOG, "simple driver expression evaluation failed: '%s'", driver->expression);
1178 return false;
1179 }
1180}
1181
1182/* Compile and cache the driver expression if necessary, with thread safety. */
1184{
1185 if (driver->expr_simple != nullptr) {
1186 return true;
1187 }
1188
1189 if (driver->type != DRIVER_TYPE_PYTHON) {
1190 return false;
1191 }
1192
1193 /* It's safe to parse in multiple threads; at worst it'll
1194 * waste some effort, but in return avoids mutex contention. */
1196
1197 /* Store the result if the field is still nullptr, or discard
1198 * it if another thread got here first. */
1199 if (atomic_cas_ptr((void **)&driver->expr_simple, nullptr, expr) != nullptr) {
1201 }
1202
1203 return true;
1204}
1205
1206/* Try using the simple expression evaluator to compute the result of the driver.
1207 * On success, stores the result and returns true; on failure result is set to 0. */
1208static bool driver_try_evaluate_simple_expr(const AnimationEvalContext *anim_eval_context,
1209 ChannelDriver *driver,
1210 ChannelDriver *driver_orig,
1211 float *result,
1212 float time)
1213{
1214 *result = 0.0f;
1215
1216 return driver_compile_simple_expr(driver_orig) &&
1217 BLI_expr_pylike_is_valid(driver_orig->expr_simple) &&
1219 anim_eval_context, driver, driver_orig->expr_simple, result, time);
1220}
1221
1226
1227/* TODO(sergey): This is somewhat weak, but we don't want neither false-positive
1228 * time dependencies nor special exceptions in the depsgraph evaluation. */
1229static bool python_driver_exression_depends_on_time(const char *expression)
1230{
1231 if (expression[0] == '\0') {
1232 /* Empty expression depends on nothing. */
1233 return false;
1234 }
1235 if (strchr(expression, '(') != nullptr) {
1236 /* Function calls are considered dependent on a time. */
1237 return true;
1238 }
1239 if (strstr(expression, "frame") != nullptr) {
1240 /* Variable `frame` depends on time. */
1241 /* TODO(sergey): This is a bit weak, but not sure about better way of handling this. */
1242 return true;
1243 }
1244 /* Possible indirect time relation s should be handled via variable targets. */
1245 return false;
1246}
1247
1249{
1250 if (driver->type != DRIVER_TYPE_PYTHON) {
1251 return false;
1252 }
1253
1255 /* Simple expressions can be checked exactly. */
1257 }
1258
1259 /* Otherwise, heuristically scan the expression string for certain patterns. */
1261}
1262
1264 bool expr_changed,
1265 bool varname_changed)
1266{
1267 if (expr_changed || varname_changed) {
1269 driver->expr_simple = nullptr;
1270 }
1271
1272#ifdef WITH_PYTHON
1273 if (expr_changed) {
1274 driver->flag |= DRIVER_FLAG_RECOMPILE;
1275 }
1276
1277 if (varname_changed) {
1278 driver->flag |= DRIVER_FLAG_RENAMEVAR;
1279 }
1280#endif
1281}
1282
1285/* -------------------------------------------------------------------- */
1290 ChannelDriver *driver,
1291 DriverVar *dvar)
1292{
1293 const DriverVarTypeInfo *dvti;
1294
1295 /* Sanity check. */
1296 if (ELEM(nullptr, driver, dvar)) {
1297 return 0.0f;
1298 }
1299
1300 /* Call the relevant callbacks to get the variable value
1301 * using the variable type info, storing the obtained value
1302 * in `dvar->curval` so that drivers can be debugged. */
1303 dvti = get_dvar_typeinfo(dvar->type);
1304
1305 if (dvti && dvti->get_value) {
1306 dvar->curval = dvti->get_value(anim_eval_context, driver, dvar);
1307 }
1308 else {
1309 dvar->curval = 0.0f;
1310 }
1311
1312 return dvar->curval;
1313}
1314
1315static void evaluate_driver_sum(const AnimationEvalContext *anim_eval_context,
1316 ChannelDriver *driver)
1317{
1318 DriverVar *dvar;
1319
1320 /* Check how many variables there are first (i.e. just one?). */
1321 if (BLI_listbase_is_single(&driver->variables)) {
1322 /* Just one target, so just use that. */
1323 dvar = static_cast<DriverVar *>(driver->variables.first);
1324 driver->curval = driver_get_variable_value(anim_eval_context, driver, dvar);
1325 return;
1326 }
1327
1328 /* More than one target, so average the values of the targets. */
1329 float value = 0.0f;
1330 int tot = 0;
1331
1332 /* Loop through targets, adding (hopefully we don't get any overflow!). */
1333 LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
1334 value += driver_get_variable_value(anim_eval_context, driver, dvar);
1335 tot++;
1336 }
1337
1338 /* Perform operations on the total if appropriate. */
1339 if (driver->type == DRIVER_TYPE_AVERAGE) {
1340 driver->curval = tot ? (value / float(tot)) : 0.0f;
1341 }
1342 else {
1343 driver->curval = value;
1344 }
1345}
1346
1347static void evaluate_driver_min_max(const AnimationEvalContext *anim_eval_context,
1348 ChannelDriver *driver)
1349{
1350 float value = 0.0f;
1351
1352 /* Loop through the variables, getting the values and comparing them to existing ones. */
1353 LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
1354 /* Get value. */
1355 float tmp_val = driver_get_variable_value(anim_eval_context, driver, dvar);
1356
1357 /* Store this value if appropriate. */
1358 if (dvar->prev) {
1359 /* Check if greater/smaller than the baseline. */
1360 if (driver->type == DRIVER_TYPE_MAX) {
1361 /* Max? */
1362 if (tmp_val > value) {
1363 value = tmp_val;
1364 }
1365 }
1366 else {
1367 /* Min? */
1368 if (tmp_val < value) {
1369 value = tmp_val;
1370 }
1371 }
1372 }
1373 else {
1374 /* First item - make this the baseline for comparisons. */
1375 value = tmp_val;
1376 }
1377 }
1378
1379 /* Store value in driver. */
1380 driver->curval = value;
1381}
1382
1384 ChannelDriver *driver,
1385 ChannelDriver *driver_orig,
1386 const AnimationEvalContext *anim_eval_context)
1387{
1388 /* Check for empty or invalid expression. */
1389 if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) {
1390 driver->curval = 0.0f;
1391 }
1392 else if (!driver_try_evaluate_simple_expr(anim_eval_context,
1393 driver,
1394 driver_orig,
1395 &driver->curval,
1396 anim_eval_context->eval_time))
1397 {
1398#ifdef WITH_PYTHON
1399 /* This evaluates the expression using Python, and returns its result:
1400 * - on errors it reports, then returns 0.0f. */
1401 BLI_mutex_lock(&python_driver_lock);
1402
1403 driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, anim_eval_context);
1404
1405 BLI_mutex_unlock(&python_driver_lock);
1406#else /* WITH_PYTHON */
1407 UNUSED_VARS(anim_rna, anim_eval_context);
1408#endif /* WITH_PYTHON */
1409 }
1410}
1411
1413 ChannelDriver *driver,
1414 ChannelDriver *driver_orig,
1415 const AnimationEvalContext *anim_eval_context)
1416{
1417 /* Check if driver can be evaluated. */
1418 if (driver_orig->flag & DRIVER_FLAG_INVALID) {
1419 return 0.0f;
1420 }
1421
1422 switch (driver->type) {
1423 case DRIVER_TYPE_AVERAGE: /* Average values of driver targets. */
1424 case DRIVER_TYPE_SUM: /* Sum values of driver targets. */
1425 evaluate_driver_sum(anim_eval_context, driver);
1426 break;
1427 case DRIVER_TYPE_MIN: /* Smallest value. */
1428 case DRIVER_TYPE_MAX: /* Largest value. */
1429 evaluate_driver_min_max(anim_eval_context, driver);
1430 break;
1431 case DRIVER_TYPE_PYTHON: /* Expression. */
1432 evaluate_driver_python(anim_rna, driver, driver_orig, anim_eval_context);
1433 break;
1434 default:
1435 /* Special 'hack' - just use stored value
1436 * This is currently used as the mechanism which allows animated settings to be able
1437 * to be changed via the UI. */
1438 break;
1439 }
1440
1441 /* Return value for driver. */
1442 return driver->curval;
1443}
1444
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
void BKE_pchan_to_mat4(const bPoseChannel *pchan, float r_chanmat[4][4])
Definition armature.cc:2837
void BKE_constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, struct bConstraintOb *cob, float mat[4][4], short from, short to, bool keep_scale)
#define DRIVER_TARGETS_LOOPER_BEGIN(dvar)
eDriverVariablePropertyResult
@ DRIVER_VAR_PROPERTY_SUCCESS
@ DRIVER_VAR_PROPERTY_FALLBACK
@ DRIVER_VAR_PROPERTY_INVALID_INDEX
@ DRIVER_VAR_PROPERTY_INVALID
#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
#define DRIVER_TARGETS_LOOPER_END
@ G_DEBUG
General operations, lookup, etc. for blender objects.
void BKE_object_to_mat4(const Object *ob, float r_mat[4][4])
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:25
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
eExprPyLike_EvalStatus
@ EXPR_PYLIKE_SUCCESS
@ EXPR_PYLIKE_DIV_BY_ZERO
@ EXPR_PYLIKE_MATH_ERROR
eExprPyLike_EvalStatus BLI_expr_pylike_eval(struct ExprPyLike_Parsed *expr, const double *param_values, int param_values_len, double *r_result)
void BLI_expr_pylike_free(struct ExprPyLike_Parsed *expr)
bool BLI_expr_pylike_is_valid(const struct ExprPyLike_Parsed *expr)
ExprPyLike_Parsed * BLI_expr_pylike_parse(const char *expression, const char **param_names, int param_names_len)
bool BLI_expr_pylike_is_using_param(const struct ExprPyLike_Parsed *expr, int index)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
void void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
ListBase BLI_listbase_from_link(struct Link *some_link)
Definition listbase.cc:787
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define M_PI
MINLINE float safe_acosf(float a)
MINLINE float safe_asinf(float a)
float mat4_to_volume_scale(const float mat[4][4])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void invert_qt_normalized(float q[4])
void mat4_to_eulO(float eul[3], short order, const float m[4][4])
float quat_split_swing_and_twist(const float q_in[4], int axis, float r_swing[4], float r_twist[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
void mat4_to_quat(float q[4], const float mat[4][4])
void compatible_eul(float eul[3], const float oldrot[3])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v4(float r[4])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define STRNCPY_UTF8(dst, src)
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
#define BLI_MUTEX_INITIALIZER
Definition BLI_threads.h:84
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
pthread_mutex_t ThreadMutex
Definition BLI_threads.h:83
#define UNUSED_VARS(...)
#define ELEM(...)
#define IN_RANGE_INCL(a, b, c)
#define BLT_I18NCONTEXT_ID_ACTION
#define CTX_DATA_(context, msgid)
bool BPY_string_is_keyword(const char *str)
float BPY_driver_exec(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const AnimationEvalContext *anim_eval_context)
void BPY_DECREF(void *pyob_ptr)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
ViewLayer * DEG_get_evaluated_view_layer(const Depsgraph *graph)
@ ID_OB
@ ROT_MODE_EUL
#define MAX_DRIVER_TARGETS
@ DTAR_TRANSCHAN_SCALEX
@ DTAR_TRANSCHAN_SCALEZ
@ DTAR_TRANSCHAN_ROTW
@ DTAR_TRANSCHAN_ROTX
@ MAX_DTAR_TRANSCHAN_TYPES
@ DTAR_TRANSCHAN_SCALE_AVG
@ DTAR_TRANSCHAN_SCALEY
@ DTAR_OPTION_USE_FALLBACK
@ DRIVER_TYPE_AVERAGE
@ DRIVER_TYPE_PYTHON
@ DRIVER_TYPE_MAX
@ DRIVER_TYPE_MIN
@ DRIVER_TYPE_SUM
@ DVAR_TYPE_LOC_DIFF
@ DVAR_TYPE_TRANSFORM_CHAN
@ DVAR_TYPE_ROT_DIFF
@ MAX_DVAR_TYPES
@ DVAR_TYPE_SINGLE_PROP
@ DVAR_TYPE_CONTEXT_PROP
@ DTAR_ROTMODE_QUATERNION
@ DTAR_ROTMODE_SWING_TWIST_X
@ DTAR_ROTMODE_EULER_MIN
@ DTAR_ROTMODE_AUTO
@ DTAR_ROTMODE_EULER_MAX
@ DTAR_ROTMODE_SWING_TWIST_Z
@ DTAR_FLAG_LOCAL_CONSTS
@ DTAR_FLAG_LOCALSPACE
@ DTAR_FLAG_ID_OB_ONLY
@ DTAR_FLAG_FALLBACK_USED
@ DTAR_FLAG_INVALID
@ DTAR_FLAG_STRUCT_REF
@ DRIVER_FLAG_INVALID
@ DRIVER_FLAG_RECOMPILE
@ DRIVER_FLAG_RENAMEVAR
#define DVAR_ALL_INVALID_FLAGS
@ DTAR_CONTEXT_PROPERTY_ACTIVE_SCENE
@ DTAR_CONTEXT_PROPERTY_ACTIVE_VIEW_LAYER
@ DVAR_FLAG_INVALID_START_CHAR
@ DVAR_FLAG_INVALID_NAME
@ DVAR_FLAG_INVALID_EMPTY
@ DVAR_FLAG_INVALID_START_NUM
@ DVAR_FLAG_INVALID_HAS_SPACE
@ DVAR_FLAG_INVALID_HAS_DOT
@ DVAR_FLAG_INVALID_HAS_SPECIAL
@ DVAR_FLAG_INVALID_PY_KEYWORD
@ CONSTRAINT_SPACE_POSE
@ CONSTRAINT_SPACE_WORLD
@ CONSTRAINT_SPACE_LOCAL
Object is a sort of wrapper for general info.
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Read Guarded memory(de)allocation.
@ PROP_FLOAT
Definition RNA_types.hh:67
@ PROP_BOOLEAN
Definition RNA_types.hh:65
@ PROP_ENUM
Definition RNA_types.hh:69
@ PROP_INT
Definition RNA_types.hh:66
constexpr PointerRNA PointerRNA_NULL
Definition RNA_types.hh:45
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE void * atomic_cas_ptr(void **v, void *old, void *_new)
double time
#define offsetof(t, d)
#define fabsf(x)
draw_view in_light_buf[] float
static float dvar_eval_transChan(const AnimationEvalContext *, ChannelDriver *driver, DriverVar *dvar)
void driver_change_variable_type(DriverVar *dvar, int type)
static float dvar_eval_singleProp(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver, DriverVar *dvar)
static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar)
static bool driver_try_evaluate_simple_expr(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver, ChannelDriver *driver_orig, float *result, float time)
void fcurve_free_driver(FCurve *fcu)
static bool driver_evaluate_simple_expr(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver, ExprPyLike_Parsed *expr, float *result, float time)
static DriverTargetContext driver_target_context_from_animation_context(const AnimationEvalContext *anim_eval_context)
static void evaluate_driver_sum(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver)
@ VAR_INDEX_FRAME
@ VAR_INDEX_CUSTOM
bool BKE_driver_expression_depends_on_time(ChannelDriver *driver)
ChannelDriver * fcurve_copy_driver(const ChannelDriver *driver)
static bool driver_get_target_context_property(const DriverTargetContext *driver_target_context, DriverTarget *dtar, PointerRNA *r_property_ptr)
DriverVar * driver_add_new_variable(ChannelDriver *driver)
float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const AnimationEvalContext *anim_eval_context)
void BKE_driver_target_matrix_to_rot_channels(float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4])
static float dvar_eval_rotDiff(const AnimationEvalContext *, ChannelDriver *driver, DriverVar *dvar)
static const DriverVarTypeInfo * get_dvar_typeinfo(int type)
static void evaluate_driver_python(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const AnimationEvalContext *anim_eval_context)
static bool python_driver_exression_depends_on_time(const char *expression)
void driver_free_variable(ListBase *variables, DriverVar *dvar)
eDriverVariablePropertyResult driver_get_variable_property(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver, DriverVar *dvar, DriverTarget *dtar, const bool allow_no_index, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
static float dvar_eval_locDiff(const AnimationEvalContext *, ChannelDriver *driver, DriverVar *dvar)
void driver_variable_unique_name(DriverVar *dvar)
static bool dtar_try_use_fallback(DriverTarget *dtar)
static float dtar_get_prop_val(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver, DriverVar *dvar, DriverTarget *dtar)
void driver_variable_name_validate(DriverVar *dvar)
float driver_get_variable_value(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver, DriverVar *dvar)
void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars)
#define END_DVAR_TYPEDEF
static bool driver_compile_simple_expr(ChannelDriver *driver)
static ExprPyLike_Parsed * driver_compile_simple_expr_impl(ChannelDriver *driver)
static bool driver_check_simple_expr_depends_on_time(const ExprPyLike_Parsed *expr)
static CLG_LogRef LOG
bool driver_get_target_property(const DriverTargetContext *driver_target_context, DriverVar *dvar, DriverTarget *dtar, PointerRNA *r_prop)
#define BEGIN_DVAR_TYPEDEF(type)
void driver_free_variable_ex(ChannelDriver *driver, DriverVar *dvar)
static void quaternion_to_angles(float quat[4], int channel)
static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES]
static void evaluate_driver_min_max(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver)
bool BKE_driver_has_simple_expression(ChannelDriver *driver)
void BKE_driver_invalidate_expression(ChannelDriver *driver, bool expr_changed, bool varname_changed)
static float dvar_eval_contextProp(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver, DriverVar *dvar)
#define GS(x)
Definition iris.cc:202
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
#define G(x, y, z)
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)
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
PropertyType RNA_property_type(PropertyRNA *prop)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
PointerRNA RNA_id_pointer_create(ID *id)
bool RNA_path_resolve_full(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
Definition rna_path.cc:537
bool RNA_path_resolve_property_full(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
Definition rna_path.cc:565
struct Depsgraph * depsgraph
Definition BKE_animsys.h:41
char expression[256]
struct ExprPyLike_Parsed * expr_simple
struct ViewLayer * view_layer
char pchan_name[64]
float(* get_value)(const AnimationEvalContext *anim_eval_context, ChannelDriver *driver, DriverVar *dvar)
short target_flags[MAX_DRIVER_TARGETS]
const char * target_names[MAX_DRIVER_TARGETS]
struct DriverVar * next
DriverTarget targets[8]
char name[64]
ChannelDriver * driver
char name[66]
Definition DNA_ID.h:425
void * first
struct bPose * pose
float loc[3]
float rot[3]
ID * owner_id
Definition RNA_types.hh:40
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
float pose_mat[4][4]
PointerRNA * ptr
Definition wm_files.cc:4126