Drivers: refactor driver_get_variable_property to return an enum.

In order to prepare for introduction of fallbacks, refactor the
function to return its status as an enumeration value. Also, move
the index range check inside the function from python-specific code.
This commit is contained in:
Alexander Gavrilov 2023-07-15 14:03:17 +03:00
parent b9074381e5
commit bbd7872680
3 changed files with 79 additions and 50 deletions

@ -134,16 +134,29 @@ struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver);
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 succesfully resolved and can be accessed. */
DRIVER_VAR_PROPERTY_SUCCESS,
/** 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.
*/
bool driver_get_variable_property(const struct AnimationEvalContext *anim_eval_context,
struct ChannelDriver *driver,
struct DriverVar *dvar,
struct DriverTarget *dtar,
struct PointerRNA *r_ptr,
struct PropertyRNA **r_prop,
int *r_index);
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.

@ -253,13 +253,15 @@ static float dtar_get_prop_val(const AnimationEvalContext *anim_eval_context,
return value;
}
bool driver_get_variable_property(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver,
DriverVar *dvar,
DriverTarget *dtar,
PointerRNA *r_ptr,
PropertyRNA **r_prop,
int *r_index)
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)
{
PointerRNA ptr;
PropertyRNA *prop;
@ -267,7 +269,7 @@ bool driver_get_variable_property(const AnimationEvalContext *anim_eval_context,
/* Sanity check. */
if (ELEM(nullptr, driver, dtar)) {
return false;
return DRIVER_VAR_PROPERTY_INVALID;
}
/* Get RNA-pointer for the data-block given in target. */
@ -281,7 +283,7 @@ bool driver_get_variable_property(const AnimationEvalContext *anim_eval_context,
driver->flag |= DRIVER_FLAG_INVALID;
dtar->flag |= DTAR_FLAG_INVALID;
return false;
return DRIVER_VAR_PROPERTY_INVALID;
}
/* Get property to read from, and get value as appropriate. */
@ -307,16 +309,34 @@ bool driver_get_variable_property(const AnimationEvalContext *anim_eval_context,
driver->flag |= DRIVER_FLAG_INVALID;
dtar->flag |= DTAR_FLAG_INVALID;
return false;
return DRIVER_VAR_PROPERTY_INVALID;
}
*r_ptr = ptr;
*r_prop = prop;
*r_index = index;
/* Verify the array index and apply fallback if appropriate. */
if (prop && RNA_property_array_check(prop)) {
if ((index < 0 && !allow_no_index) || index >= RNA_property_array_length(&ptr, prop)) {
/* Out of bounds. */
if (G.debug & G_DEBUG) {
CLOG_ERROR(&LOG,
"Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)",
ptr.owner_id->name,
dtar->rna_path,
index);
}
driver->flag |= DRIVER_FLAG_INVALID;
dtar->flag |= DTAR_FLAG_INVALID;
return DRIVER_VAR_PROPERTY_INVALID_INDEX;
}
}
/* If we're still here, we should be ok. */
dtar->flag &= ~DTAR_FLAG_INVALID;
return true;
return DRIVER_VAR_PROPERTY_SUCCESS;
}
static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar)

@ -27,45 +27,41 @@ PyObject *pyrna_driver_get_variable_value(const AnimationEvalContext *anim_eval_
DriverVar *dvar,
DriverTarget *dtar)
{
PyObject *driver_arg = nullptr;
PointerRNA ptr;
PropertyRNA *prop = nullptr;
int index;
if (driver_get_variable_property(anim_eval_context, driver, dvar, dtar, &ptr, &prop, &index)) {
if (prop) {
if (index != -1) {
if (index < RNA_property_array_length(&ptr, prop) && index >= 0) {
/* object, property & index */
driver_arg = pyrna_array_index(&ptr, prop, index);
}
else {
/* out of range, pass */
}
}
else {
/* object & property */
const PropertyType type = RNA_property_type(prop);
if (type == PROP_ENUM) {
/* Note that enum's are converted to strings by default,
* we want to avoid that, see: #52213 */
driver_arg = PyLong_FromLong(RNA_property_enum_get(&ptr, prop));
}
else {
driver_arg = pyrna_prop_to_py(&ptr, prop);
}
}
}
else {
switch (driver_get_variable_property(
anim_eval_context, driver, dvar, dtar, true, &ptr, &prop, &index))
{
case DRIVER_VAR_PROPERTY_SUCCESS:
/* object only */
driver_arg = pyrna_struct_CreatePyObject(&ptr);
}
}
else {
/* can't resolve path, pass */
if (!prop) {
return pyrna_struct_CreatePyObject(&ptr);
}
/* object, property & index */
if (index >= 0) {
return pyrna_array_index(&ptr, prop, index);
}
/* object & property (enum) */
if (RNA_property_type(prop) == PROP_ENUM) {
/* Note that enum's are converted to strings by default,
* we want to avoid that, see: #52213 */
return PyLong_FromLong(RNA_property_enum_get(&ptr, prop));
}
/* object & property */
return pyrna_prop_to_py(&ptr, prop);
case DRIVER_VAR_PROPERTY_INVALID:
case DRIVER_VAR_PROPERTY_INVALID_INDEX:
/* can't resolve path, pass */
return nullptr;
}
return driver_arg;
return nullptr;
}
PyObject *pyrna_driver_self_from_anim_rna(PathResolvedRNA *anim_rna)