[Bf-blender-cvs] [846080e] master: Fix Py API array assignment not clamping values

Campbell Barton noreply at git.blender.org
Tue Mar 8 05:42:08 CET 2016


Commit: 846080e6bcc02fb7af999a274385907c4e1b2279
Author: Campbell Barton
Date:   Tue Mar 8 15:33:28 2016 +1100
Branches: master
https://developer.blender.org/rB846080e6bcc02fb7af999a274385907c4e1b2279

Fix Py API array assignment not clamping values

===================================================================

M	source/blender/python/intern/bpy_rna_array.c

===================================================================

diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c
index 033f8a3..38931cd 100644
--- a/source/blender/python/intern/bpy_rna_array.c
+++ b/source/blender/python/intern/bpy_rna_array.c
@@ -46,11 +46,32 @@
 
 #define MAX_ARRAY_DIMENSION 10
 
-typedef void (*ItemConvertFunc)(PyObject *, char *);
+struct ItemConvertArgData;
+
+typedef void (*ItemConvertFunc)(const struct ItemConvertArgData *arg, PyObject *, char *);
 typedef int (*ItemTypeCheckFunc)(PyObject *);
 typedef void (*RNA_SetArrayFunc)(PointerRNA *, PropertyRNA *, const char *);
 typedef void (*RNA_SetIndexFunc)(PointerRNA *, PropertyRNA *, int index, void *);
 
+struct ItemConvertArgData {
+	union {
+		struct {
+			int range[2];
+		} int_data;
+		struct {
+			float range[2];
+		} float_data;
+	};
+};
+
+/**
+ * Callback and args needed to apply the value (clamp range for now)
+ */
+typedef struct ItemConvert_FuncArg {
+	ItemConvertFunc func;
+	struct ItemConvertArgData arg;
+} ItemConvert_FuncArg;
+
 /*
  * arr[3][4][5]
  *     0  1  2  <- dimension index
@@ -328,28 +349,31 @@ static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop,
 	}
 }
 
-static char *copy_value_single(PyObject *item, PointerRNA *ptr, PropertyRNA *prop,
-                               char *data, unsigned int item_size, int *index,
-                               ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index)
+static char *copy_value_single(
+        PyObject *item, PointerRNA *ptr, PropertyRNA *prop,
+        char *data, unsigned int item_size, int *index,
+        const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index)
 {
 	if (!data) {
-		char value[sizeof(int)];
+		union { float fl; int i; } value_buf;
+		char *value = (void *)&value_buf;
 
-		convert_item(item, value);
+		convert_item->func(&convert_item->arg, item, value);
 		rna_set_index(ptr, prop, *index, value);
-		*index = *index + 1;
+		(*index) += 1;
 	}
 	else {
-		convert_item(item, data);
+		convert_item->func(&convert_item->arg, item, data);
 		data += item_size;
 	}
 
 	return data;
 }
 
-static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop,
-                         int dim, char *data, unsigned int item_size, int *index,
-                         ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index)
+static char *copy_values(
+        PyObject *seq, PointerRNA *ptr, PropertyRNA *prop,
+        int dim, char *data, unsigned int item_size, int *index,
+        const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index)
 {
 	int totdim = RNA_property_array_dimension(ptr, prop, NULL);
 	const Py_ssize_t seq_size = PySequence_Size(seq);
@@ -410,9 +434,10 @@ static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop,
 	return data;
 }
 
-static int py_to_array(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop,
-                       char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size,
-                       ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
+static int py_to_array(
+        PyObject *seq, PointerRNA *ptr, PropertyRNA *prop,
+        char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size,
+        const ItemConvert_FuncArg *convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
 {
 	/*int totdim, dim_size[MAX_ARRAY_DIMENSION];*/
 	int totitem;
@@ -464,10 +489,11 @@ static int py_to_array(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop,
 	return 0;
 }
 
-static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop,
-                             int lvalue_dim, int arrayoffset, int index,
-                             ItemTypeCheckFunc check_item_type, const char *item_type_str,
-                             ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix)
+static int py_to_array_index(
+        PyObject *py, PointerRNA *ptr, PropertyRNA *prop,
+        int lvalue_dim, int arrayoffset, int index,
+        ItemTypeCheckFunc check_item_type, const char *item_type_str,
+        const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix)
 {
 	int totdim, dimsize[MAX_ARRAY_DIMENSION];
 	int totitem, i;
@@ -513,17 +539,23 @@ static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop,
 	return 0;
 }
 
-static void py_to_float(PyObject *py, char *data)
+static void py_to_float(const struct ItemConvertArgData *arg, PyObject *py, char *data)
 {
-	*(float *)data = (float)PyFloat_AsDouble(py);
+	const float *range = arg->float_data.range;
+	float value = (float)PyFloat_AsDouble(py);
+	CLAMP(value, range[0], range[1]);
+	*(float *)data = value;
 }
 
-static void py_to_int(PyObject *py, char *data)
+static void py_to_int(const struct ItemConvertArgData *arg, PyObject *py, char *data)
 {
-	*(int *)data = (int)PyLong_AsLong(py);
+	const int *range = arg->int_data.range;
+	int value = (int)PyLong_AsLong(py);
+	CLAMP(value, range[0], range[1]);
+	*(int *)data = value;
 }
 
-static void py_to_bool(PyObject *py, char *data)
+static void py_to_bool(const struct ItemConvertArgData *UNUSED(arg), PyObject *py, char *data)
 {
 	*(int *)data = (int)PyObject_IsTrue(py);
 }
@@ -560,27 +592,72 @@ static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *
 	RNA_property_boolean_set_index(ptr, prop, index, *(int *)value);
 }
 
+static void convert_item_init_float(
+        PointerRNA *ptr, PropertyRNA *prop,
+        ItemConvert_FuncArg *convert_item)
+{
+	float *range = convert_item->arg.float_data.range;
+	convert_item->func = py_to_float;
+	RNA_property_float_range(ptr, prop, &range[0], &range[1]);
+}
+
+static void convert_item_init_int(
+        PointerRNA *ptr, PropertyRNA *prop,
+        ItemConvert_FuncArg *convert_item)
+{
+	int *range = convert_item->arg.int_data.range;
+	convert_item->func = py_to_int;
+	RNA_property_int_range(ptr, prop, &range[0], &range[1]);
+}
+
+static void convert_item_init_bool(
+        PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop),
+        ItemConvert_FuncArg *convert_item)
+{
+	convert_item->func = py_to_bool;
+}
+
 int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data,
                       PyObject *py, const char *error_prefix)
 {
 	int ret;
 	switch (RNA_property_type(prop)) {
 		case PROP_FLOAT:
-			ret = py_to_array(py, ptr, prop, param_data, py_float_check, "float", sizeof(float),
-			                  py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix);
+		{
+			ItemConvert_FuncArg convert_item;
+			convert_item_init_float(ptr, prop, &convert_item);
+
+			ret = py_to_array(
+			        py, ptr, prop, param_data, py_float_check, "float", sizeof(float),
+			        &convert_item, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix);
 			break;
+		}
 		case PROP_INT:
-			ret = py_to_array(py, ptr, prop, param_data, py_int_check, "int", sizeof(int),
-			                  py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix);
+		{
+			ItemConvert_FuncArg convert_item;
+			convert_item_init_int(ptr, prop, &convert_item);
+
+			ret = py_to_array(
+			        py, ptr, prop, param_data, py_int_check, "int", sizeof(int),
+			        &convert_item, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix);
 			break;
+		}
 		case PROP_BOOLEAN:
-			ret = py_to_array(py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(int),
-			                  py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix);
+		{
+			ItemConvert_FuncArg convert_item;
+			convert_item_init_bool(ptr, prop, &convert_item);
+
+			ret = py_to_array(
+			        py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(int),
+			        &convert_item, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix);
 			break;
+		}
 		default:
+		{
 			PyErr_SetString(PyExc_TypeError, "not an array type");
 			ret = -1;
 			break;
+		}
 	}
 
 	return ret;
@@ -592,21 +669,44 @@ int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, in
 	int ret;
 	switch (RNA_property_type(prop)) {
 		case PROP_FLOAT:
-			ret = py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index,
-			                        py_float_check, "float", py_to_float, float_set_index, error_prefix);
+		{
+			ItemConvert_FuncArg convert_item;
+			convert_item_init_float(ptr, prop, &convert_item);
+
+			ret = py_to_array_index(
+			        py, ptr, prop, arraydim, arrayoffset, index,
+			        py_float_check, "float",
+			        &convert_item, float_set_index, error_prefix);
 			break;
+		}
 		case PROP_INT:
-			ret = py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index,
-			                        py_int_check, "int", py_to_int, int_set_index, error_prefix);
+		{
+			ItemConvert_FuncArg convert_item;
+			convert_item_init_int(ptr, prop, &convert_item);
+
+			ret = py_to_array_index(
+			        py, ptr, prop, arraydim, arrayoffset, index,
+			        py_int_check, "int",
+			        &convert_item, int_set_index, error_prefix);
 			break;
+		}
 		case PROP_BOOLEAN:
-			ret = py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index,
-			                        py_bool_check, "boolean", py_to_bool, bool_set_index, error_prefix);
+		{
+			ItemConvert_FuncArg convert_item;
+			convert_item_init_bool(ptr, prop, &convert_item);
+
+			ret = py_to_array_index(
+			        py, ptr, prop, arraydim, arrayoffset, index,
+			        py_bool_check, "boolean",
+			        &convert_item, bool_set_index, error_prefix);
 			break;
+		}
 		default:
+		{
 			PyErr_SetString(PyExc_TypeError, "not an array type");
 			ret = -1;
 			break;
+		}
 	}
 
 	return ret;




More information about the Bf-blender-cvs mailing list