tornavis/source/blender/blenkernel/BKE_fcurve_driver.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

194 lines
6.2 KiB
C
Raw Normal View History

/* SPDX-FileCopyrightText: 2009 Blender Authors, Joshua Leung. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*/
#include "DNA_curve_types.h"
#ifdef __cplusplus
extern "C" {
#endif
T77086 Animation: Passing Dependency Graph to Drivers Custom driver functions need access to the dependency graph that is triggering the evaluation of the driver. This patch passes the dependency graph pointer through all the animation-related calls. Instead of passing the evaluation time to functions, the code now passes an `AnimationEvalContext` pointer: ``` typedef struct AnimationEvalContext { struct Depsgraph *const depsgraph; const float eval_time; } AnimationEvalContext; ``` These structs are read-only, meaning that the code cannot change the evaluation time. Note that the `depsgraph` pointer itself is const, but it points to a non-const depsgraph. FCurves and Drivers can be evaluated at a different time than the current scene time, for example when evaluating NLA strips. This means that, even though the current time is stored in the dependency graph, we need an explicit evaluation time. There are two functions that allow creation of `AnimationEvalContext` objects: - `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float eval_time)`, which creates a new context object from scratch, and - `BKE_animsys_eval_context_construct_at(AnimationEvalContext *anim_eval_context, float eval_time)`, which can be used to create a `AnimationEvalContext` with the same depsgraph, but at a different time. This makes it possible to later add fields without changing any of the code that just want to change the eval time. This also provides a fix for T75553, although it does require a change to the custom driver function. The driver should call `custom_function(depsgraph)`, and the function should use that depsgraph instead of information from `bpy.context`. Reviewed By: brecht, sergey Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
struct AnimationEvalContext;
struct ChannelDriver;
struct DriverTarget;
struct DriverVar;
struct FCurve;
struct PathResolvedRNA;
struct PointerRNA;
struct PropertyRNA;
Drivers: Introduce the Context Properties Drivers: Introduce the Context Properties The goal: allow accessing context dependent data, such as active scene camera without linking to a specific scene data-block. This is useful in cases when, for example, geometry node setup needs to be aware of the camera position. A possible work-around without changes like this is to have some scene evaluation hook which will update driver variables for the currently evaluating scene. But this raises an issue of linking: it is undesirable that the asset scene is linked to the shot file. Surely, it is possible to have post-evaluation handler to clear the variables, but it all starts to be quite messy. Not to mention possible threading conflicts. Another possibility of introducing a way to achieve the goal is to make it so the dependency graph somehow parses the python expression where artists can (and already are trying to) type something like: depsgraph.scene.camera.matrix_world.col[3][0] But this is not only tricky to implement properly and reliably, it hits two limitations: - Currently dependency graph can only easily resolve dependencies to a RNA property. - Some properties access which are valid in Python are not considered valid RNA properties by the existing property resolution functions: `camera.matrix_world[3][0]` is a valid RNA property, but `camera.matrix_world.col[3][0]` is not. Using driver variables allows to have visual feedback when the path resolution fails, and there is no way to visualize errors in the python expression itself. This change introduces the new variable type: Context Property. Using this variable type makes allows to choose between Active Scene and Active View Layer. These scene and view layer are resolved during the driver evaluation time, based on the current dependency graph. This allows to create a driver variable in the following configuration: - Type: Context Property - Context Property: Active Scene - Path: camera.matrix_world[3][0] The naming is a bit confusing. Tried my best to keep it clear keeping two aspects in mind: using UI naming when possible, and follow the existing naming. A lot of the changes are related on making it so the required data is available from the variable evaluation functions. It wasn't really clear what the data would be, and the scope of the changes, so it is done together with the functional changes. It seems that there is some variable evaluation logic duplicated in the `bpy_rna_driver.c`. This change does not change it. It is not really clear why this separate code path with much more limited scope of supported target types is even needed. There is also a possible change in the behavior of the dependency graph: it is now using ID of the resolved path when building driver variables. It used to use the variable ID. In common cases they match, but when going into nested data-blocks it is actually correct to use relation to the resolved ID. Not sure if there was some code to ensure that, which now can be resolved. Also not sure whether it is still needed to ensure the ID specified in the driver target is build as well. Intuitively it is not needed. Pull Request #105132
2023-03-06 16:01:47 +01:00
struct Scene;
struct ViewLayer;
/* ************** F-Curve Drivers ***************** */
/* With these iterators for convenience, the variables "tarIndex" and "dtar" can be
* accessed directly from the code using them, but it is not recommended that their
* values be changed to point at other slots...
*/
/* convenience looper over ALL driver targets for a given variable (even the unused ones) */
#define DRIVER_TARGETS_LOOPER_BEGIN(dvar) \
{ \
DriverTarget *dtar = &dvar->targets[0]; \
int tarIndex = 0; \
for (; tarIndex < MAX_DRIVER_TARGETS; tarIndex++, dtar++)
/* convenience looper over USED driver targets only */
#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar) \
{ \
DriverTarget *dtar = &dvar->targets[0]; \
int tarIndex = 0; \
for (; tarIndex < dvar->num_targets; tarIndex++, dtar++)
/* tidy up for driver targets loopers */
#define DRIVER_TARGETS_LOOPER_END \
} \
((void)0)
/* ---------------------- */
/**
* This frees the driver itself.
*/
void fcurve_free_driver(struct FCurve *fcu);
/**
* This makes a copy of the given driver.
*/
struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver);
Drivers: Introduce the Context Properties Drivers: Introduce the Context Properties The goal: allow accessing context dependent data, such as active scene camera without linking to a specific scene data-block. This is useful in cases when, for example, geometry node setup needs to be aware of the camera position. A possible work-around without changes like this is to have some scene evaluation hook which will update driver variables for the currently evaluating scene. But this raises an issue of linking: it is undesirable that the asset scene is linked to the shot file. Surely, it is possible to have post-evaluation handler to clear the variables, but it all starts to be quite messy. Not to mention possible threading conflicts. Another possibility of introducing a way to achieve the goal is to make it so the dependency graph somehow parses the python expression where artists can (and already are trying to) type something like: depsgraph.scene.camera.matrix_world.col[3][0] But this is not only tricky to implement properly and reliably, it hits two limitations: - Currently dependency graph can only easily resolve dependencies to a RNA property. - Some properties access which are valid in Python are not considered valid RNA properties by the existing property resolution functions: `camera.matrix_world[3][0]` is a valid RNA property, but `camera.matrix_world.col[3][0]` is not. Using driver variables allows to have visual feedback when the path resolution fails, and there is no way to visualize errors in the python expression itself. This change introduces the new variable type: Context Property. Using this variable type makes allows to choose between Active Scene and Active View Layer. These scene and view layer are resolved during the driver evaluation time, based on the current dependency graph. This allows to create a driver variable in the following configuration: - Type: Context Property - Context Property: Active Scene - Path: camera.matrix_world[3][0] The naming is a bit confusing. Tried my best to keep it clear keeping two aspects in mind: using UI naming when possible, and follow the existing naming. A lot of the changes are related on making it so the required data is available from the variable evaluation functions. It wasn't really clear what the data would be, and the scope of the changes, so it is done together with the functional changes. It seems that there is some variable evaluation logic duplicated in the `bpy_rna_driver.c`. This change does not change it. It is not really clear why this separate code path with much more limited scope of supported target types is even needed. There is also a possible change in the behavior of the dependency graph: it is now using ID of the resolved path when building driver variables. It used to use the variable ID. In common cases they match, but when going into nested data-blocks it is actually correct to use relation to the resolved ID. Not sure if there was some code to ensure that, which now can be resolved. Also not sure whether it is still needed to ensure the ID specified in the driver target is build as well. Intuitively it is not needed. Pull Request #105132
2023-03-06 16:01:47 +01:00
/**
* Get property from which the specific property can be found from.
*
* This depends on the type of `dvar`:
*
* - For the Single Property the `r_prop` is a pointer to an ID, which is used to resolve the
* target rna_path.
*
* - For Transform Channel, Rotational Difference, Distance the `r_prop` is a pointer to an
* object from which transformation is read.
*
* - For Context Property the `r_prop` points to a resolved data corresponding to the
* dtar->context_property accessed from the given evaluated context. This could either be an ID
* property for Active Scene, or a data property for Active View Layer.
*
* If the target property can not be resolved false is returned.
*/
typedef struct DriverTargetContext {
struct Scene *scene;
struct ViewLayer *view_layer;
} DriverTargetContext;
bool driver_get_target_property(const DriverTargetContext *driver_target_context,
struct DriverVar *dvar,
struct DriverTarget *dtar,
struct PointerRNA *r_prop);
/**
* Copy driver variables from src_vars list to dst_vars list.
*/
void driver_variables_copy(struct ListBase *dst_vars, const struct ListBase *src_vars);
/**
* Compute channel values for a rotational Transform Channel driver variable.
*/
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]);
/**
* Perform actual freeing driver variable and remove it from the given list.
*/
void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar);
/**
* Free the driver variable and do extra updates.
*/
void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar);
/**
* Change the type of driver variable.
*/
void driver_change_variable_type(struct DriverVar *dvar, int type);
/**
* Validate driver variable name (after being renamed).
*/
void driver_variable_name_validate(struct DriverVar *dvar);
/**
* Ensure the driver variable's name is unique.
*
* Assumes the driver variable has already been assigned to the driver, so that
2022-01-06 03:54:52 +01:00
* the `prev/next` pointers can be used to find the other variables.
*/
void driver_variable_unique_name(struct DriverVar *dvar);
/**
* Add a new driver variable.
*/
struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver);
/**
* Evaluate a Driver Variable to get a value that contributes to the final.
*/
Drivers: Introduce the Context Properties Drivers: Introduce the Context Properties The goal: allow accessing context dependent data, such as active scene camera without linking to a specific scene data-block. This is useful in cases when, for example, geometry node setup needs to be aware of the camera position. A possible work-around without changes like this is to have some scene evaluation hook which will update driver variables for the currently evaluating scene. But this raises an issue of linking: it is undesirable that the asset scene is linked to the shot file. Surely, it is possible to have post-evaluation handler to clear the variables, but it all starts to be quite messy. Not to mention possible threading conflicts. Another possibility of introducing a way to achieve the goal is to make it so the dependency graph somehow parses the python expression where artists can (and already are trying to) type something like: depsgraph.scene.camera.matrix_world.col[3][0] But this is not only tricky to implement properly and reliably, it hits two limitations: - Currently dependency graph can only easily resolve dependencies to a RNA property. - Some properties access which are valid in Python are not considered valid RNA properties by the existing property resolution functions: `camera.matrix_world[3][0]` is a valid RNA property, but `camera.matrix_world.col[3][0]` is not. Using driver variables allows to have visual feedback when the path resolution fails, and there is no way to visualize errors in the python expression itself. This change introduces the new variable type: Context Property. Using this variable type makes allows to choose between Active Scene and Active View Layer. These scene and view layer are resolved during the driver evaluation time, based on the current dependency graph. This allows to create a driver variable in the following configuration: - Type: Context Property - Context Property: Active Scene - Path: camera.matrix_world[3][0] The naming is a bit confusing. Tried my best to keep it clear keeping two aspects in mind: using UI naming when possible, and follow the existing naming. A lot of the changes are related on making it so the required data is available from the variable evaluation functions. It wasn't really clear what the data would be, and the scope of the changes, so it is done together with the functional changes. It seems that there is some variable evaluation logic duplicated in the `bpy_rna_driver.c`. This change does not change it. It is not really clear why this separate code path with much more limited scope of supported target types is even needed. There is also a possible change in the behavior of the dependency graph: it is now using ID of the resolved path when building driver variables. It used to use the variable ID. In common cases they match, but when going into nested data-blocks it is actually correct to use relation to the resolved ID. Not sure if there was some code to ensure that, which now can be resolved. Also not sure whether it is still needed to ensure the ID specified in the driver target is build as well. Intuitively it is not needed. Pull Request #105132
2023-03-06 16:01:47 +01:00
float driver_get_variable_value(const struct AnimationEvalContext *anim_eval_context,
struct ChannelDriver *driver,
struct DriverVar *dvar);
typedef enum eDriverVariablePropertyResult {
/** The property reference has been successfully resolved and can be accessed. */
DRIVER_VAR_PROPERTY_SUCCESS,
/** Evaluation should use the fallback value. */
DRIVER_VAR_PROPERTY_FALLBACK,
/** The target property could not be resolved. */
DRIVER_VAR_PROPERTY_INVALID,
/** The property was resolved (output parameters are set),
* but the array index is out of bounds. */
DRIVER_VAR_PROPERTY_INVALID_INDEX
} eDriverVariablePropertyResult;
/**
* Same as 'dtar_get_prop_val'. but get the RNA property.
*/
eDriverVariablePropertyResult driver_get_variable_property(
const struct AnimationEvalContext *anim_eval_context,
struct ChannelDriver *driver,
struct DriverVar *dvar,
struct DriverTarget *dtar,
bool allow_no_index,
struct PointerRNA *r_ptr,
struct PropertyRNA **r_prop,
int *r_index);
/**
* Check if the expression in the driver conforms to the simple subset.
*/
bool BKE_driver_has_simple_expression(struct ChannelDriver *driver);
/**
* Check if the expression in the driver may depend on the current frame.
*/
bool BKE_driver_expression_depends_on_time(struct ChannelDriver *driver);
/**
* Reset cached compiled expression data.
*/
void BKE_driver_invalidate_expression(struct ChannelDriver *driver,
bool expr_changed,
bool varname_changed);
/**
* Evaluate an Channel-Driver to get a 'time' value to use
* instead of `anim_eval_context->eval_time`.
*
* - `anim_eval_context->eval_time` is the frame at which F-Curve is being evaluated.
* - Has to return a float value.
* - \a driver_orig is where we cache Python expressions, in case of copy-on-eval
*/
float evaluate_driver(struct PathResolvedRNA *anim_rna,
struct ChannelDriver *driver,
struct ChannelDriver *driver_orig,
T77086 Animation: Passing Dependency Graph to Drivers Custom driver functions need access to the dependency graph that is triggering the evaluation of the driver. This patch passes the dependency graph pointer through all the animation-related calls. Instead of passing the evaluation time to functions, the code now passes an `AnimationEvalContext` pointer: ``` typedef struct AnimationEvalContext { struct Depsgraph *const depsgraph; const float eval_time; } AnimationEvalContext; ``` These structs are read-only, meaning that the code cannot change the evaluation time. Note that the `depsgraph` pointer itself is const, but it points to a non-const depsgraph. FCurves and Drivers can be evaluated at a different time than the current scene time, for example when evaluating NLA strips. This means that, even though the current time is stored in the dependency graph, we need an explicit evaluation time. There are two functions that allow creation of `AnimationEvalContext` objects: - `BKE_animsys_eval_context_construct(Depsgraph *depsgraph, float eval_time)`, which creates a new context object from scratch, and - `BKE_animsys_eval_context_construct_at(AnimationEvalContext *anim_eval_context, float eval_time)`, which can be used to create a `AnimationEvalContext` with the same depsgraph, but at a different time. This makes it possible to later add fields without changing any of the code that just want to change the eval time. This also provides a fix for T75553, although it does require a change to the custom driver function. The driver should call `custom_function(depsgraph)`, and the function should use that depsgraph instead of information from `bpy.context`. Reviewed By: brecht, sergey Differential Revision: https://developer.blender.org/D8047
2020-07-17 17:38:09 +02:00
const struct AnimationEvalContext *anim_eval_context);
#ifdef __cplusplus
}
#endif