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