Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArystanbek Dyussenov <arystan.d@gmail.com>2009-08-25 21:06:36 +0400
committerArystanbek Dyussenov <arystan.d@gmail.com>2009-08-25 21:06:36 +0400
commit706a4c22b54ede250fbdb2c2bd772c63cdbf7d09 (patch)
treee9398918b950b98e3fa17741d67fe7b94915f89f
parent7288bacad9bbe5e670de3454c9a64dee0c3d920c (diff)
Implemented dynamic and multidimensional array support in RNA.
Example code: http://www.pasteall.org/7332/c. New API functions: http://www.pasteall.org/7330/c. Maximum number of dimensions is currently limited to 3, but can be increased arbitrarily if needed. What this means for ID property access: * MeshFace.verts - dynamic array, size 3 or 4 depending on MFace.v4 * MeshTextureFace.uv - dynamic, 2-dimensional array, size depends on MFace.v4 * Object.matrix - 2-dimensional array What this means for functions: * more intuitive API possibility, for example: Mesh.add_vertices([(x, y, z), (x, y, z), ...]) Mesh.add_faces([(1, 2, 3), (4, 5, 6), ...]) Python part is not complete yet, e.g. it is possible to: MeshFace.verts = (1, 2, 3) # even if Mesh.verts is (1, 2, 3, 4) and vice-versa MeshTextureFace.uv = [(0.0, 0.0)] * 4 # only if a corresponding MFace is a quad but the following won't work: MeshTextureFace.uv[3] = (0.0, 0.0) # setting uv[3] modifies MTFace.uv[1][0] instead of MTFace.uv[3]
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c12
-rw-r--r--source/blender/blenkernel/intern/fcurve.c6
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c2
-rw-r--r--source/blender/editors/animation/drivers.c6
-rw-r--r--source/blender/editors/animation/keyframing.c10
-rw-r--r--source/blender/editors/animation/keyingsets.c4
-rw-r--r--source/blender/editors/interface/interface.c18
-rw-r--r--source/blender/editors/interface/interface_anim.c2
-rw-r--r--source/blender/editors/interface/interface_layout.c10
-rw-r--r--source/blender/editors/interface/interface_templates.c2
-rw-r--r--source/blender/editors/interface/interface_utils.c4
-rw-r--r--source/blender/editors/space_outliner/outliner.c4
-rw-r--r--source/blender/makesrna/RNA_access.h4
-rw-r--r--source/blender/makesrna/RNA_define.h8
-rw-r--r--source/blender/makesrna/RNA_types.h3
-rw-r--r--source/blender/makesrna/intern/makesrna.c8
-rw-r--r--source/blender/makesrna/intern/rna_access.c45
-rw-r--r--source/blender/makesrna/intern/rna_define.c46
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h11
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c97
-rw-r--r--source/blender/makesrna/intern/rna_object.c4
-rw-r--r--source/blender/python/intern/bpy_array.c235
-rw-r--r--source/blender/python/intern/bpy_rna.c131
-rw-r--r--source/blender/python/intern/bpy_rna.h5
24 files changed, 513 insertions, 164 deletions
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 44d73a7f5b4..df7004d3f6b 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -441,19 +441,19 @@ static short animsys_write_rna_setting (PointerRNA *ptr, char *path, int array_i
switch (RNA_property_type(prop))
{
case PROP_BOOLEAN:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(&new_ptr, prop))
RNA_property_boolean_set_index(&new_ptr, prop, array_index, (int)value);
else
RNA_property_boolean_set(&new_ptr, prop, (int)value);
break;
case PROP_INT:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(&new_ptr, prop))
RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value);
else
RNA_property_int_set(&new_ptr, prop, (int)value);
break;
case PROP_FLOAT:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(&new_ptr, prop))
RNA_property_float_set_index(&new_ptr, prop, array_index, value);
else
RNA_property_float_set(&new_ptr, prop, value);
@@ -1178,19 +1178,19 @@ void nladata_flush_channels (ListBase *channels)
switch (RNA_property_type(prop))
{
case PROP_BOOLEAN:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(ptr, prop))
RNA_property_boolean_set_index(ptr, prop, array_index, (int)value);
else
RNA_property_boolean_set(ptr, prop, (int)value);
break;
case PROP_INT:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(ptr, prop))
RNA_property_int_set_index(ptr, prop, array_index, (int)value);
else
RNA_property_int_set(ptr, prop, (int)value);
break;
case PROP_FLOAT:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(ptr, prop))
RNA_property_float_set_index(ptr, prop, array_index, value);
else
RNA_property_float_set(ptr, prop, value);
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 90bf08059d7..31f6e2c6067 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -698,19 +698,19 @@ float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar)
if (RNA_path_resolve(&id_ptr, path, &ptr, &prop)) {
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(&ptr, prop))
value= (float)RNA_property_boolean_get_index(&ptr, prop, index);
else
value= (float)RNA_property_boolean_get(&ptr, prop);
break;
case PROP_INT:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(&ptr, prop))
value= (float)RNA_property_int_get_index(&ptr, prop, index);
else
value= (float)RNA_property_int_get(&ptr, prop);
break;
case PROP_FLOAT:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(&ptr, prop))
value= RNA_property_float_get_index(&ptr, prop, index);
else
value= RNA_property_float_get(&ptr, prop);
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index ecf0bdbf285..26edf930f0b 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -147,7 +147,7 @@ void getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
propname= (char *)RNA_property_ui_name(prop);
/* Array Index - only if applicable */
- if (RNA_property_array_length(prop)) {
+ if (RNA_property_array_length(&ptr, prop)) {
char c= RNA_property_array_item_char(prop, fcu->array_index);
/* we need to write the index to a temp buffer (in py syntax) */
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 849e2d2eede..e7b7d785d7b 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -157,7 +157,7 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla
/* fill in current value for python */
if(type == DRIVER_TYPE_PYTHON) {
PropertyType proptype= RNA_property_type(prop);
- int array= RNA_property_array_length(prop);
+ int array= RNA_property_array_length(&ptr, prop);
char *expression= fcu->driver->expression;
int val, maxlen= sizeof(fcu->driver->expression);
float fval;
@@ -241,7 +241,7 @@ static int add_driver_button_exec (bContext *C, wmOperator *op)
if (path) {
if (all) {
- length= RNA_property_array_length(prop);
+ length= RNA_property_array_length(&ptr, prop);
if (length) index= 0;
else length= 1;
@@ -303,7 +303,7 @@ static int remove_driver_button_exec (bContext *C, wmOperator *op)
if (path) {
if (all) {
- length= RNA_property_array_length(prop);
+ length= RNA_property_array_length(&ptr, prop);
if(length) index= 0;
else length= 1;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index b62c69c7b38..dc73011549c 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -503,19 +503,19 @@ static float setting_get_rna_value (PointerRNA *ptr, PropertyRNA *prop, int inde
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(ptr, prop))
value= (float)RNA_property_boolean_get_index(ptr, prop, index);
else
value= (float)RNA_property_boolean_get(ptr, prop);
break;
case PROP_INT:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(ptr, prop))
value= (float)RNA_property_int_get_index(ptr, prop, index);
else
value= (float)RNA_property_int_get(ptr, prop);
break;
case PROP_FLOAT:
- if (RNA_property_array_length(prop))
+ if (RNA_property_array_length(ptr, prop))
value= RNA_property_float_get_index(ptr, prop, index);
else
value= RNA_property_float_get(ptr, prop);
@@ -1313,7 +1313,7 @@ static int insert_key_button_exec (bContext *C, wmOperator *op)
if (path) {
if (all) {
- length= RNA_property_array_length(prop);
+ length= RNA_property_array_length(&ptr, prop);
if(length) index= 0;
else length= 1;
@@ -1396,7 +1396,7 @@ static int delete_key_button_exec (bContext *C, wmOperator *op)
if (path) {
if (all) {
- length= RNA_property_array_length(prop);
+ length= RNA_property_array_length(&ptr, prop);
if(length) index= 0;
else length= 1;
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index d22fe763ad4..21f969467aa 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -925,7 +925,7 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *
RNA_id_pointer_create(ksp->id, &id_ptr);
if (RNA_path_resolve(&id_ptr, ksp->rna_path, &ptr, &prop) && prop)
- arraylen= RNA_property_array_length(prop);
+ arraylen= RNA_property_array_length(&ptr, prop);
}
/* we should do at least one step */
@@ -1048,7 +1048,7 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *
RNA_id_pointer_create(cks->id, &id_ptr);
if (RNA_path_resolve(&id_ptr, path, &ptr, &prop) && prop)
- arraylen= RNA_property_array_length(prop);
+ arraylen= RNA_property_array_length(&ptr, prop);
}
/* for each possible index, perform operation
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 9bd6c2577ff..3c6e12905d6 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1089,7 +1089,7 @@ void ui_get_but_vectorf(uiBut *but, float *vec)
vec[0]= vec[1]= vec[2]= 0.0f;
if(RNA_property_type(prop) == PROP_FLOAT) {
- tot= RNA_property_array_length(prop);
+ tot= RNA_property_array_length(&but->rnapoin, prop);
tot= MIN2(tot, 3);
for(a=0; a<tot; a++)
@@ -1123,7 +1123,7 @@ void ui_set_but_vectorf(uiBut *but, float *vec)
prop= but->rnaprop;
if(RNA_property_type(prop) == PROP_FLOAT) {
- tot= RNA_property_array_length(prop);
+ tot= RNA_property_array_length(&but->rnapoin, prop);
tot= MIN2(tot, 3);
for(a=0; a<tot; a++)
@@ -1181,19 +1181,19 @@ double ui_get_but_val(uiBut *but)
switch(RNA_property_type(prop)) {
case PROP_BOOLEAN:
- if(RNA_property_array_length(prop))
+ if(RNA_property_array_length(&but->rnapoin, prop))
value= RNA_property_boolean_get_index(&but->rnapoin, prop, but->rnaindex);
else
value= RNA_property_boolean_get(&but->rnapoin, prop);
break;
case PROP_INT:
- if(RNA_property_array_length(prop))
+ if(RNA_property_array_length(&but->rnapoin, prop))
value= RNA_property_int_get_index(&but->rnapoin, prop, but->rnaindex);
else
value= RNA_property_int_get(&but->rnapoin, prop);
break;
case PROP_FLOAT:
- if(RNA_property_array_length(prop))
+ if(RNA_property_array_length(&but->rnapoin, prop))
value= RNA_property_float_get_index(&but->rnapoin, prop, but->rnaindex);
else
value= RNA_property_float_get(&but->rnapoin, prop);
@@ -1245,19 +1245,19 @@ void ui_set_but_val(uiBut *but, double value)
if(RNA_property_editable(&but->rnapoin, prop)) {
switch(RNA_property_type(prop)) {
case PROP_BOOLEAN:
- if(RNA_property_array_length(prop))
+ if(RNA_property_array_length(&but->rnapoin, prop))
RNA_property_boolean_set_index(&but->rnapoin, prop, but->rnaindex, value);
else
RNA_property_boolean_set(&but->rnapoin, prop, value);
break;
case PROP_INT:
- if(RNA_property_array_length(prop))
+ if(RNA_property_array_length(&but->rnapoin, prop))
RNA_property_int_set_index(&but->rnapoin, prop, but->rnaindex, value);
else
RNA_property_int_set(&but->rnapoin, prop, value);
break;
case PROP_FLOAT:
- if(RNA_property_array_length(prop))
+ if(RNA_property_array_length(&but->rnapoin, prop))
RNA_property_float_set_index(&but->rnapoin, prop, but->rnaindex, value);
else
RNA_property_float_set(&but->rnapoin, prop, value);
@@ -2414,7 +2414,7 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1,
but->rnapoin= *ptr;
but->rnaprop= prop;
- if(RNA_property_array_length(but->rnaprop))
+ if(RNA_property_array_length(&but->rnapoin, but->rnaprop))
but->rnaindex= index;
else
but->rnaindex= 0;
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 2993a1aba15..784d820ea52 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -217,7 +217,7 @@ void ui_but_anim_menu(bContext *C, uiBut *but)
pup= uiPupMenuBegin(C, RNA_property_ui_name(but->rnaprop), 0);
layout= uiPupMenuLayout(pup);
- length= RNA_property_array_length(but->rnaprop);
+ length= RNA_property_array_length(&but->rnapoin, but->rnaprop);
if(but->flag & UI_BUT_ANIMATED_KEY) {
if(length) {
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 3b4471bd4b9..a52afcb1a92 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -760,7 +760,7 @@ void uiItemO(uiLayout *layout, char *name, int icon, char *opname)
/* RNA property items */
-static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PropertyRNA *prop, int index, int *r_w, int *r_h)
+static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int *r_w, int *r_h)
{
PropertyType type;
PropertySubType subtype;
@@ -769,7 +769,7 @@ static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PropertyRNA
/* arbitrary extended width by type */
type= RNA_property_type(prop);
subtype= RNA_property_subtype(prop);
- len= RNA_property_array_length(prop);
+ len= RNA_property_array_length(ptr, prop);
if(ELEM3(type, PROP_STRING, PROP_POINTER, PROP_ENUM) && !name[0])
name= "non-empty text";
@@ -819,7 +819,7 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper
/* retrieve info */
type= RNA_property_type(prop);
- len= RNA_property_array_length(prop);
+ len= RNA_property_array_length(ptr, prop);
/* set name and icon */
if(!name)
@@ -846,7 +846,7 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper
expand= (flag & UI_ITEM_R_EXPAND);
/* get size */
- ui_item_rna_size(layout, name, icon, prop, index, &w, &h);
+ ui_item_rna_size(layout, name, icon, ptr, prop, index, &w, &h);
/* array property */
if(index == RNA_NO_INDEX && len > 0)
@@ -1132,7 +1132,7 @@ void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *p
/* create button */
block= uiLayoutGetBlock(layout);
- ui_item_rna_size(layout, name, icon, prop, 0, &w, &h);
+ ui_item_rna_size(layout, name, icon, ptr, prop, 0, &w, &h);
but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h);
ui_but_add_search(but, ptr, prop, searchptr, searchprop);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 56badedaded..4cfc44e56c8 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1258,7 +1258,7 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
* the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
* - for now, only split into groups if if group will have at least 5 items
*/
- layers= RNA_property_array_length(prop);
+ layers= RNA_property_array_length(ptr, prop);
cols= (layers / 2) + (layers % 2);
groups= ((cols / 2) < 5) ? (1) : (cols / 2);
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 997ac8b78c6..5b44f6544d1 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -72,7 +72,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
{
uiBut *but=NULL;
const char *propname= RNA_property_identifier(prop);
- int arraylen= RNA_property_array_length(prop);
+ int arraylen= RNA_property_array_length(ptr, prop);
switch(RNA_property_type(prop)) {
case PROP_BOOLEAN: {
@@ -81,7 +81,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
if(arraylen && index == -1)
return NULL;
- length= RNA_property_array_length(prop);
+ length= RNA_property_array_length(ptr, prop);
if(length)
value= RNA_property_boolean_get_index(ptr, prop, index);
diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c
index 762ad82344b..d564573a543 100644
--- a/source/blender/editors/space_outliner/outliner.c
+++ b/source/blender/editors/space_outliner/outliner.c
@@ -1084,7 +1084,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->flag |= TE_LAZY_CLOSED;
}
else if(ELEM3(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
- tot= RNA_property_array_length(prop);
+ tot= RNA_property_array_length(ptr, prop);
if(!(tselem->flag & TSE_CLOSED)) {
for(a=0; a<tot; a++)
@@ -3721,7 +3721,7 @@ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreEle
/* item is part of an array, so must set the array_index */
*array_index= te->index;
}
- else if (RNA_property_array_length(prop)) {
+ else if (RNA_property_array_length(ptr, prop)) {
/* entire array was selected, so keyframe all */
*flag |= KSP_FLAG_WHOLE_ARRAY;
}
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index fb351efed66..cb54fe2ad8d 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -581,8 +581,10 @@ PropertySubType RNA_property_subtype(PropertyRNA *prop);
PropertyUnit RNA_property_unit(PropertyRNA *prop);
int RNA_property_flag(PropertyRNA *prop);
-int RNA_property_array_length(PropertyRNA *prop);
+int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop);
+int RNA_property_dynamic_array_set_length(PointerRNA *ptr, PropertyRNA *prop, int length);
char RNA_property_array_item_char(PropertyRNA *prop, int index);
+unsigned short RNA_property_array_dimension(PropertyRNA *prop, unsigned short dim_size[]);
int RNA_property_string_maxlength(PropertyRNA *prop);
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 33f5d7137b8..1c6837bbcc8 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -88,11 +88,15 @@ void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc);
PropertyRNA *RNA_def_float(StructOrFunctionRNA *cont, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
PropertyRNA *RNA_def_float_vector(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
PropertyRNA *RNA_def_float_color(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
-PropertyRNA *RNA_def_float_matrix(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
+PropertyRNA *RNA_def_float_matrix(StructOrFunctionRNA *cont, const char *identifier, int len, int rowsize, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
PropertyRNA *RNA_def_float_rotation(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value,
float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
PropertyRNA *RNA_def_float_array(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value,
float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
+ /*
+PropertyRNA *RNA_def_float_dynamic_array(StructOrFunctionRNA *cont, const char *identifier, float hardmin, float hardmax,
+ const char *ui_name, const char *ui_description, float softmin, float softmax, unsigned int dimension, unsigned short dim_size[]);
+ */
PropertyRNA *RNA_def_float_percentage(StructOrFunctionRNA *cont, const char *identifier, float default_value, float hardmin, float hardmax,
const char *ui_name, const char *ui_description, float softmin, float softmax);
@@ -123,6 +127,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop, const char *structname,
void RNA_def_property_flag(PropertyRNA *prop, int flag);
void RNA_def_property_clear_flag(PropertyRNA *prop, int flag);
void RNA_def_property_array(PropertyRNA *prop, int arraylength);
+void RNA_def_property_multidimensional_array(PropertyRNA *prop, int arraylength, unsigned short arraydimension, unsigned short dimsize[]);
void RNA_def_property_range(PropertyRNA *prop, double min, double max);
void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item);
@@ -146,6 +151,7 @@ void RNA_def_property_ui_icon(PropertyRNA *prop, int icon, int consecutive);
void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *updatefunc);
void RNA_def_property_editable_func(PropertyRNA *prop, const char *editable);
+void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength, const char *setlength);
void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const char *set);
void RNA_def_property_int_funcs(PropertyRNA *prop, const char *get, const char *set, const char *range);
void RNA_def_property_float_funcs(PropertyRNA *prop, const char *get, const char *set, const char *range);
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 042f7578cf4..1acbfb21385 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -152,7 +152,8 @@ typedef enum PropertyFlag {
PROP_IDPROPERTY = 1024,
PROP_RAW_ACCESS = 8192,
PROP_RAW_ARRAY = 16384,
- PROP_FREE_POINTERS = 32768
+ PROP_FREE_POINTERS = 32768,
+ PROP_DYNAMIC = 131072 /* for dynamic arrays, and retvals of type string */
} PropertyFlag;
typedef struct CollectionPropertyIterator {
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index fa3a5a40686..0c90a28a0e9 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -1724,6 +1724,14 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
rna_print_c_string(f, prop->description); fprintf(f, ",\n\t");
fprintf(f, "%d,\n", prop->icon);
fprintf(f, "\t%s, %s|%s, %d,\n", rna_property_typename(prop->type), rna_property_subtypename(prop->subtype), rna_property_subtype_unit(prop->subtype), prop->arraylength);
+ {
+ int i;
+ int tot= sizeof(prop->dimsize) / sizeof(prop->dimsize[0]);
+ fprintf(f, "\t%s, %s, %d, {", rna_function_string(prop->getlength), rna_function_string(prop->setlength), (int)prop->arraydimension);
+ for(i= 0; i < tot; i++) {
+ fprintf(f, i == tot - 1 ? "%d},\n" : "%d, ", (int)prop->dimsize[i]);
+ }
+ }
fprintf(f, "\t%s, %d, %s,\n", rna_function_string(prop->update), prop->noteflag, rna_function_string(prop->editable));
if(prop->flag & PROP_RAW_ACCESS) rna_set_raw_offset(f, srna, prop);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index c2f1f31a4bc..e71dcc2a586 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -343,10 +343,11 @@ const char *rna_ensure_property_name(PropertyRNA *prop)
return ((IDProperty*)prop)->name;
}
-int rna_ensure_property_array_length(PropertyRNA *prop)
+int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
{
- if(prop->magic == RNA_MAGIC)
- return prop->arraylength;
+ if(prop->magic == RNA_MAGIC) {
+ return prop->getlength ? prop->getlength(ptr) : prop->arraylength;
+ }
else {
IDProperty *idprop= (IDProperty*)prop;
@@ -549,9 +550,27 @@ int RNA_property_flag(PropertyRNA *prop)
return rna_ensure_property(prop)->flag;
}
-int RNA_property_array_length(PropertyRNA *prop)
+int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
{
- return rna_ensure_property_array_length(prop);
+ return rna_ensure_property_array_length(ptr, prop);
+}
+
+int RNA_property_dynamic_array_set_length(PointerRNA *ptr, PropertyRNA *prop, int length)
+{
+ if (prop->setlength)
+ return prop->setlength(ptr, length);
+ else
+ prop->arraylength= length; /* function parameters only? */
+
+ return 1;
+}
+
+unsigned short RNA_property_array_dimension(PropertyRNA *prop, unsigned short dimsize[])
+{
+ if (dimsize && prop->arraydimension > 1) {
+ memcpy(dimsize, prop->dimsize, sizeof(prop->dimsize[0]) * (prop->arraydimension - 1));
+ }
+ return prop->arraydimension;
}
char RNA_property_array_item_char(PropertyRNA *prop, int index)
@@ -1684,7 +1703,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
}
/* check item array */
- itemlen= RNA_property_array_length(itemprop);
+ itemlen= RNA_property_array_length(&itemptr, itemprop);
/* try to access as raw array */
if(RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
@@ -1736,7 +1755,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
iprop= RNA_struct_find_property(&itemptr, propname);
if(iprop) {
- itemlen= RNA_property_array_length(iprop);
+ itemlen= RNA_property_array_length(&itemptr, iprop);
itemtype= RNA_property_type(iprop);
}
else {
@@ -2675,7 +2694,7 @@ char *RNA_pointer_as_string(PointerRNA *ptr)
char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
int type = RNA_property_type(prop);
- int len = RNA_property_array_length(prop);
+ int len = RNA_property_array_length(ptr, prop);
int i;
DynStr *dynstr= BLI_dynstr_new();
@@ -2905,6 +2924,12 @@ void RNA_parameter_list_free(ParameterList *parms)
for(tot= 0; parm; parm= parm->next) {
if(parm->type == PROP_COLLECTION)
BLI_freelistN((ListBase*)((char*)parms->data+tot));
+ else if (parm->flag & PROP_DYNAMIC) {
+ /* for dynamic arrays and strings, data is a pointer to an array */
+ char *array= *(char**)((char*)parms->data+tot);
+ if(array)
+ MEM_freeN(array);
+ }
tot+= rna_parameter_size(parm);
}
@@ -3277,7 +3302,7 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt
type= RNA_property_type(parm);
ftype= format[ofs++];
- len= RNA_property_array_length(parm);
+ len= RNA_property_array_length(&funcptr, parm);
alen= rna_function_format_array_length(format, ofs, flen);
if (len!=alen) {
@@ -3342,7 +3367,7 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt
type= RNA_property_type(parm);
ftype= format[ofs++];
- len= RNA_property_array_length(parm);
+ len= RNA_property_array_length(&funcptr, parm);
alen= rna_function_format_array_length(format, ofs, flen);
if (len!=alen) {
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 3b0db949350..1f51b3ff34c 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -1028,6 +1028,26 @@ void RNA_def_property_array(PropertyRNA *prop, int arraylength)
DefRNA.error= 1;
break;
}
+
+ prop->arraydimension= 1;
+}
+
+void RNA_def_property_multidimensional_array(PropertyRNA *prop, int arraylength, unsigned short dimension, unsigned short dimsize[])
+{
+ StructRNA *srna= DefRNA.laststruct;
+
+ if (dimension < 1 || dimension > RNA_MAX_ARRAY_DIMENSION) {
+ fprintf(stderr, "RNA_def_property_multidimensional_array: %s.%s, array dimension must be between 1 and %d.\n", srna->identifier, prop->identifier, RNA_MAX_ARRAY_DIMENSION);
+ DefRNA.error= 1;
+ return;
+ }
+
+ RNA_def_property_array(prop, arraylength);
+
+ prop->arraydimension= dimension;
+
+ if (dimension > 1)
+ memcpy(prop->dimsize, dimsize, sizeof(dimsize[0]) * (dimension - 1));
}
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
@@ -1688,6 +1708,23 @@ void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *func)
prop->update= (UpdateFunc)func;
}
+void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength, const char *setlength)
+{
+ if(!DefRNA.preprocess) {
+ fprintf(stderr, "RNA_def_property_*_funcs: only during preprocessing.\n");
+ return;
+ }
+
+ if (!(prop->flag & PROP_DYNAMIC)) {
+ fprintf(stderr, "RNA_def_property_dynamic_array_funcs: property is a not dynamic array.\n");
+ DefRNA.error= 1;
+ return;
+ }
+
+ if(getlength) prop->getlength= (PropArrayLengthGetFunc)getlength;
+ if(setlength) prop->setlength= (PropArrayLengthSetFunc)setlength;
+}
+
void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const char *set)
{
StructRNA *srna= DefRNA.laststruct;
@@ -2085,14 +2122,15 @@ PropertyRNA *RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identif
}
-PropertyRNA *RNA_def_float_matrix(StructOrFunctionRNA *cont_, const char *identifier, int len, const float *default_value,
+PropertyRNA *RNA_def_float_matrix(StructOrFunctionRNA *cont_, const char *identifier, int len, int rowsize, const float *default_value,
float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
{
ContainerRNA *cont= cont_;
PropertyRNA *prop;
+ unsigned short dimsize[1]= {rowsize};
prop= RNA_def_property(cont, identifier, PROP_FLOAT, PROP_MATRIX);
- if(len != 0) RNA_def_property_array(prop, len);
+ if(len != 0) RNA_def_property_multidimensional_array(prop, len, 2, dimsize);
if(default_value) RNA_def_property_float_array_default(prop, default_value);
if(hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
@@ -2292,6 +2330,10 @@ int rna_parameter_size(PropertyRNA *parm)
int len= parm->arraylength;
if(len > 0) {
+
+ if (parm->flag & PROP_DYNAMIC)
+ return sizeof(void *);
+
switch (ptype) {
case PROP_BOOLEAN:
case PROP_INT:
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index 12bd876ce52..d706fd5ac19 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -40,6 +40,7 @@ struct IDProperty;
struct GHash;
#define RNA_MAX_ARRAY 32
+#define RNA_MAX_ARRAY_DIMENSION 3
/* Function Callbacks */
@@ -49,6 +50,8 @@ typedef struct IDProperty* (*IDPropertiesFunc)(struct PointerRNA *ptr, int creat
typedef struct StructRNA *(*StructRefineFunc)(struct PointerRNA *ptr);
typedef char *(*StructPathFunc)(struct PointerRNA *ptr);
+typedef int (*PropArrayLengthGetFunc)(struct PointerRNA *ptr);
+typedef int (*PropArrayLengthSetFunc)(struct PointerRNA *ptr, int length);
typedef int (*PropBooleanGetFunc)(struct PointerRNA *ptr);
typedef void (*PropBooleanSetFunc)(struct PointerRNA *ptr, int value);
typedef void (*PropBooleanArrayGetFunc)(struct PointerRNA *ptr, int *values);
@@ -131,6 +134,14 @@ struct PropertyRNA {
PropertySubType subtype;
/* if an array this is > 0, specifying the length */
unsigned int arraylength;
+ /* these, if non-NULL, override arraylength */
+ PropArrayLengthGetFunc getlength;
+ /* if NULL, length cannot be changed by a user */
+ PropArrayLengthSetFunc setlength;
+ /* used only for dynamic arrays for now, default 1 */
+ unsigned short arraydimension;
+ /* dimension sizes for dimensions greater than 1, first dimension size is not specified */
+ unsigned short dimsize[RNA_MAX_ARRAY_DIMENSION - 1];
/* callback for updates on change */
UpdateFunc update;
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 84190d60d11..4d53986be4f 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -398,6 +398,51 @@ static void rna_MeshTextureFace_uv4_set(PointerRNA *ptr, const float *values)
mtface->uv[3][1]= values[1];
}
+static int rna_CustomDataData_numverts(PointerRNA *ptr, int type)
+{
+ Mesh *me= (Mesh*)ptr->id.data;
+ CustomData *fdata= rna_mesh_fdata(me);
+ CustomDataLayer *cdl;
+ int a;
+ size_t b;
+
+ for(cdl=fdata->layers, a=0; a<fdata->totlayer; cdl++, a++) {
+ if(cdl->type == type) {
+ b= ((char*)ptr->data - ((char*)cdl->data))/CustomData_sizeof(type);
+ if(b >= 0 && b < me->totface)
+ return (me->mface[b].v4? 4: 3);
+ }
+ }
+
+ return 0;
+}
+
+static int rna_MeshTextureFace_uv_get_length(PointerRNA *ptr)
+{
+ return rna_CustomDataData_numverts(ptr, CD_MTFACE) * 2;
+}
+
+static int rna_MeshTextureFace_uv_set_length(PointerRNA *ptr, int length)
+{
+ return length == rna_MeshTextureFace_uv_get_length(ptr);
+}
+
+static void rna_MeshTextureFace_uv_get(PointerRNA *ptr, float *values)
+{
+ MTFace *mtface= (MTFace*)ptr->data;
+ int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
+
+ memcpy(values, mtface->uv, totvert * 2 * sizeof(float));
+}
+
+static void rna_MeshTextureFace_uv_set(PointerRNA *ptr, const float *values)
+{
+ MTFace *mtface= (MTFace*)ptr->data;
+ int totvert= rna_CustomDataData_numverts(ptr, CD_MTFACE);
+
+ memcpy(mtface->uv, values, totvert * 2 * sizeof(float));
+}
+
static void rna_MeshTextureFaceLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Mesh *me= (Mesh*)ptr->id.data;
@@ -660,6 +705,40 @@ static void rna_TextureFace_image_set(PointerRNA *ptr, PointerRNA value)
tf->tpage= (struct Image*)id;
}
+static int rna_MeshFace_verts_get_length(PointerRNA *ptr)
+{
+ MFace *face= (MFace*)ptr->data;
+ return face->v4 ? 4 : 3;
+}
+
+static int rna_MeshFace_verts_set_length(PointerRNA *ptr, int length)
+{
+ MFace *face= (MFace*)ptr->data;
+ if (length == 3) {
+ face->v4= 0;
+ }
+ else if(length == 4) {
+ face->v4= 1;
+ }
+ else
+ return 0;
+
+ return 1;
+}
+
+static void rna_MeshFace_verts_get(PointerRNA *ptr, int *values)
+{
+ MFace *face= (MFace*)ptr->data;
+ int verts[4] = {face->v1, face->v2, face->v3, face->v4};
+ memcpy(values, verts, (face->v4 ? 4 : 3) * sizeof(int));
+}
+
+static void rna_MeshFace_verts_set(PointerRNA *ptr, const int *values)
+{
+ MFace *face= (MFace*)ptr->data;
+ memcpy(&face->v1, values, (face->v4 ? 4 : 3) * sizeof(int));
+}
+
/* path construction */
static char *rna_VertexGroupElement_path(PointerRNA *ptr)
@@ -882,11 +961,21 @@ static void rna_def_mface(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_MeshFace_path");
RNA_def_struct_ui_icon(srna, ICON_FACESEL);
+ /*
+ // XXX allows creating invalid meshes
prop= RNA_def_property(srna, "verts", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "v1");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Vertices", "Vertex indices");
+ */
+
// XXX allows creating invalid meshes
+ prop= RNA_def_property(srna, "verts", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_MeshFace_verts_get_length", "rna_MeshFace_verts_set_length");
+ RNA_def_property_int_funcs(prop, "rna_MeshFace_verts_get", "rna_MeshFace_verts_set", NULL);
+ RNA_def_property_ui_text(prop, "Vertices", "Vertex indices");
prop= RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "mat_nr");
@@ -923,6 +1012,7 @@ static void rna_def_mtface(BlenderRNA *brna)
{TF_ALPHA, "ALPHA", 0, "Alpha", "Render polygon transparent, depending on alpha channel of the texture"},
{TF_CLIP, "CLIPALPHA", 0, "Clip Alpha", "Use the images alpha values clipped with no blending (binary alpha)"},
{0, NULL, 0, NULL, NULL}};
+ unsigned short uv_dim[1]= {2};
srna= RNA_def_struct(brna, "MeshTextureFaceLayer", NULL);
RNA_def_struct_ui_text(srna, "Mesh Texture Face Layer", "Layer of texture faces in a Mesh datablock.");
@@ -1041,6 +1131,13 @@ static void rna_def_mtface(BlenderRNA *brna)
RNA_def_property_array(prop, 2);
RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv4_get", "rna_MeshTextureFace_uv4_set", NULL);
RNA_def_property_ui_text(prop, "UV 4", "");
+
+ prop= RNA_def_property(srna, "uv", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_multidimensional_array(prop, 4 * 2, 2, uv_dim);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_MeshTextureFace_uv_get_length", "rna_MeshTextureFace_uv_set_length");
+ RNA_def_property_float_funcs(prop, "rna_MeshTextureFace_uv_get", "rna_MeshTextureFace_uv_set", NULL);
+ RNA_def_property_ui_text(prop, "UV", "");
}
static void rna_def_msticky(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index bad36025eda..f0b055bd0e8 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1029,6 +1029,8 @@ static void rna_def_object(BlenderRNA *brna)
{OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing."},
{0, NULL, 0, NULL, NULL}};
+ unsigned short matrix_dimsize[]= {4};
+
srna= RNA_def_struct(brna, "Object", "ID");
RNA_def_struct_ui_text(srna, "Object", "Object datablock defining an object in a scene..");
RNA_def_struct_clear_flag(srna, STRUCT_ID_REFCOUNT);
@@ -1190,7 +1192,7 @@ static void rna_def_object(BlenderRNA *brna)
/* matrix */
prop= RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "obmat");
- RNA_def_property_array(prop, 16);
+ RNA_def_property_multidimensional_array(prop, 16, 2, matrix_dimsize);
RNA_def_property_ui_text(prop, "Matrix", "Transformation matrix.");
/* collections */
diff --git a/source/blender/python/intern/bpy_array.c b/source/blender/python/intern/bpy_array.c
new file mode 100644
index 00000000000..d52bfda202d
--- /dev/null
+++ b/source/blender/python/intern/bpy_array.c
@@ -0,0 +1,235 @@
+/**
+ *
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Arystanbek Dyussenov
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "Python.h"
+
+#include "bpy_rna.h"
+
+#include "RNA_access.h"
+
+#include "BLI_string.h"
+
+#include "MEM_guardedalloc.h"
+
+typedef void (*ItemConvertFunc)(PyObject *, char *);
+typedef int (*ItemTypeCheckFunc)(PyObject *);
+typedef void (*RNA_SetArrayFunc)(PointerRNA *, PropertyRNA *, const char *);
+
+/* Ensures that a python sequence has an expected number of items/sub-items and items are of expected type. */
+static int pyrna_validate_array(PyObject *seq, unsigned short dim, unsigned short totdim, unsigned short dim_size[],
+ ItemTypeCheckFunc check_item_type, const char *item_type_str, char *error_str, int error_str_size)
+{
+ int i;
+ if (dim < totdim) {
+ for (i= 0; i < PySequence_Length(seq); i++) {
+ PyObject *item;
+ int ok= 1;
+ item= PySequence_GetItem(seq, i);
+
+ if (!PySequence_Check(item)) {
+ BLI_snprintf(error_str, error_str_size, "expected a %d-dimensional sequence of %s", (int)totdim, item_type_str);
+ ok= 0;
+ }
+ else if (PySequence_Length(item) != dim_size[dim - 1]) {
+ BLI_snprintf(error_str, error_str_size, "dimension %d should contain %d items", (int)dim, (int)dim_size[dim - 1]);
+ ok= 0;
+ }
+
+ if (!pyrna_validate_array(item, dim + 1, totdim, dim_size, check_item_type, item_type_str, error_str, error_str_size)) {
+ ok= 0;
+ }
+
+ Py_DECREF(item);
+
+ if (!ok)
+ return 0;
+ }
+ }
+ else {
+ for (i= 0; i < PySequence_Length(seq); i++) {
+ PyObject *item= PySequence_GetItem(seq, i);
+
+ if (!check_item_type(item)) {
+ Py_DECREF(item);
+
+ BLI_snprintf(error_str, error_str_size, "sequence items should be of type %s", item_type_str);
+ return 0;
+ }
+
+ Py_DECREF(item);
+ }
+ }
+
+ return 1;
+}
+
+/* Returns the number of items in a single- or multi-dimensional sequence. */
+static int pyrna_count_items(PyObject *seq)
+{
+ int totitem= 0;
+
+ if (PySequence_Check(seq)) {
+ int i;
+ for (i= 0; i < PySequence_Length(seq); i++) {
+ PyObject *item= PySequence_GetItem(seq, i);
+ totitem += pyrna_count_items(item);
+ Py_DECREF(item);
+ }
+ }
+ else
+ totitem= 1;
+
+ return totitem;
+}
+
+static int pyrna_apply_array_length(PointerRNA *ptr, PropertyRNA *prop, int totitem, char *error_str, int error_str_size)
+{
+ if (RNA_property_flag(prop) & PROP_DYNAMIC) {
+ /* length can be flexible */
+ if (RNA_property_array_length(ptr, prop) != totitem) {
+ if (!RNA_property_dynamic_array_set_length(ptr, prop, totitem)) {
+ BLI_snprintf(error_str, error_str_size, "%s.%s: array length cannot be changed to %d", RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), totitem);
+ return 0;
+ }
+ }
+ }
+ else {
+ /* length is a constraint */
+ int len= RNA_property_array_length(ptr, prop);
+ if (totitem != len) {
+ BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static char *pyrna_py_to_array(PyObject *seq, unsigned short dim, unsigned short totdim, char *data, unsigned int item_size, ItemConvertFunc convert_item)
+{
+ unsigned int i;
+ for (i= 0; i < PySequence_Length(seq); i++) {
+ PyObject *item= PySequence_GetItem(seq, i);
+
+ if (dim < totdim) {
+ data= pyrna_py_to_array(item, dim + 1, totdim, data, item_size, convert_item);
+ }
+ else {
+ convert_item(item, data);
+ data += item_size;
+ }
+
+ Py_DECREF(item);
+ }
+
+ return data;
+}
+
+static int pyrna_py_to_array_generic(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, char *error_str, int error_str_size,
+ ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array)
+{
+ unsigned short totdim, dim_size[100];
+ int totitem;
+ char *data= NULL;
+
+ totdim= RNA_property_array_dimension(prop, dim_size);
+
+ if (!pyrna_validate_array(py, 1, totdim, dim_size, check_item_type, item_type_str, error_str, error_str_size))
+ return 0;
+
+ totitem= pyrna_count_items(py);
+
+ if (!pyrna_apply_array_length(ptr, prop, totitem, error_str, error_str_size))
+ return 0;
+
+ if (totitem) {
+ if (!param_data || RNA_property_flag(prop) & PROP_DYNAMIC)
+ data= MEM_callocN(item_size * totitem, "pyrna primitive type array");
+ else
+ data= param_data;
+
+ pyrna_py_to_array(py, 1, totdim, data, item_size, convert_item);
+
+ if (param_data) {
+ if (RNA_property_flag(prop) & PROP_DYNAMIC) {
+ /* not freeing allocated mem, RNA_parameter_list_free will do this */
+ *(char**)param_data= data;
+ }
+ }
+ else {
+ /* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */
+ rna_set_array(ptr, prop, data);
+ MEM_freeN(data);
+ }
+ }
+
+ return 1;
+}
+
+static void pyrna_py_to_float(PyObject *py, char *data)
+{
+ *(float*)data= (float)PyFloat_AsDouble(py);
+}
+
+static void pyrna_py_to_int(PyObject *py, char *data)
+{
+ *(int*)data= (int)PyLong_AsSsize_t(py);
+}
+
+static void pyrna_py_to_boolean(PyObject *py, char *data)
+{
+ *(int*)data= (int)PyObject_IsTrue(py);
+}
+
+static int py_float_check(PyObject *py)
+{
+ return PyFloat_Check(py);
+}
+
+static int py_int_check(PyObject *py)
+{
+ return PyLong_Check(py);
+}
+
+static int py_bool_check(PyObject *py)
+{
+ return PyBool_Check(py);
+}
+
+int pyrna_py_to_float_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, char *error_str, int error_str_size)
+{
+ return pyrna_py_to_array_generic(py, ptr, prop, param_data, error_str, error_str_size,
+ py_float_check, "float", sizeof(float), pyrna_py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array);
+}
+
+int pyrna_py_to_int_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, char *error_str, int error_str_size)
+{
+ return pyrna_py_to_array_generic(py, ptr, prop, param_data, error_str, error_str_size,
+ py_int_check, "int", sizeof(int), pyrna_py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array);
+}
+
+int pyrna_py_to_boolean_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, char *error_str, int error_str_size)
+{
+ return pyrna_py_to_array_generic(py, ptr, prop, param_data, error_str, error_str_size,
+ py_bool_check, "boolean", sizeof(int), pyrna_py_to_boolean, (RNA_SetArrayFunc)RNA_property_boolean_set_array);
+}
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 70ff8e48084..3902a9fd9b5 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -246,7 +246,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
{
PyObject *ret;
int type = RNA_property_type(prop);
- int len = RNA_property_array_length(prop);
+ int len = RNA_property_array_length(ptr, prop);
if (len > 0) {
/* resolve the array from a new pytype */
@@ -469,128 +469,43 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
{
/* XXX hard limits should be checked here */
int type = RNA_property_type(prop);
- int len = RNA_property_array_length(prop);
+ int len = RNA_property_array_length(ptr, prop);
if (len > 0) {
- PyObject *item;
- int py_len = -1;
- int i;
-
+ char error_str[512];
+ int ok= 1;
#ifdef USE_MATHUTILS
if(MatrixObject_Check(value)) {
MatrixObject *mat = (MatrixObject*)value;
if(!BaseMath_ReadCallback(mat))
return -1;
-
- py_len = mat->rowSize * mat->colSize;
} else /* continue... */
#endif
- if (PySequence_Check(value)) {
- py_len= (int)PySequence_Length(value);
- }
- else {
+ if (!PySequence_Check(value)) {
PyErr_Format(PyExc_TypeError, "%.200s RNA array assignment expected a sequence instead of %.200s instance.", error_prefix, Py_TYPE(value)->tp_name);
return -1;
}
/* done getting the length */
- if (py_len != len) {
- PyErr_Format(PyExc_TypeError, "%.200s python sequence length %d did not match the RNA array length %d.", error_prefix, py_len, len);
- return -1;
- }
-
/* for arrays we have a limited number of types */
switch (type) {
case PROP_BOOLEAN:
- {
- int *param_arr;
- if(data) param_arr= (int*)data;
- else param_arr= MEM_mallocN(sizeof(int) * len, "pyrna bool array");
-
-
- /* collect the variables before assigning, incase one of them is incorrect */
- for (i=0; i<len; i++) {
- item = PySequence_GetItem(value, i);
- param_arr[i] = PyObject_IsTrue( item );
- Py_DECREF(item);
-
- if (param_arr[i] < 0) {
- if(data==NULL)
- MEM_freeN(param_arr);
- PyErr_Format(PyExc_AttributeError, "%.200s one or more of the values in the sequence is not a boolean", error_prefix);
- return -1;
- }
- }
- if(data==NULL) {
- RNA_property_boolean_set_array(ptr, prop, param_arr);
- MEM_freeN(param_arr);
- }
-
+ ok= pyrna_py_to_boolean_array(value, ptr, prop, data, error_str, sizeof(error_str));
break;
- }
case PROP_INT:
- {
- int *param_arr;
- if(data) param_arr= (int*)data;
- else param_arr= MEM_mallocN(sizeof(int) * len, "pyrna int array");
-
-
- /* collect the variables */
- for (i=0; i<len; i++) {
- item = PySequence_GetItem(value, i);
- param_arr[i] = (int)PyLong_AsSsize_t(item); /* deal with any errors later */
- Py_DECREF(item);
- }
-
- if (PyErr_Occurred()) {
- if(data==NULL)
- MEM_freeN(param_arr);
- PyErr_Format(PyExc_AttributeError, "%.200s one or more of the values in the sequence could not be used as an int", error_prefix);
- return -1;
- }
- if(data==NULL) {
- RNA_property_int_set_array(ptr, prop, param_arr);
- MEM_freeN(param_arr);
- }
+ ok= pyrna_py_to_int_array(value, ptr, prop, data, error_str, sizeof(error_str));
break;
- }
case PROP_FLOAT:
- {
- float *param_arr;
- if(data) param_arr = (float*)data;
- else param_arr = MEM_mallocN(sizeof(float) * len, "pyrna float array");
-
-
-#ifdef USE_MATHUTILS
- if(MatrixObject_Check(value) && RNA_property_subtype(prop) == PROP_MATRIX) {
- MatrixObject *mat = (MatrixObject*)value;
- memcpy(param_arr, mat->contigPtr, sizeof(float) * len);
- } else /* continue... */
-#endif
- {
- /* collect the variables */
- for (i=0; i<len; i++) {
- item = PySequence_GetItem(value, i);
- param_arr[i] = (float)PyFloat_AsDouble(item); /* deal with any errors later */
- Py_DECREF(item);
- }
- }
-
- if (PyErr_Occurred()) {
- if(data==NULL)
- MEM_freeN(param_arr);
- PyErr_Format(PyExc_AttributeError, "%.200s one or more of the values in the sequence could not be used as a float", error_prefix);
- return -1;
- }
- if(data==NULL) {
- RNA_property_float_set_array(ptr, prop, param_arr);
- MEM_freeN(param_arr);
- }
+ ok= pyrna_py_to_float_array(value, ptr, prop, data, error_str, sizeof(error_str));
break;
}
+ if (!ok) {
+ PyErr_Format(PyExc_AttributeError, "%.200s %s", error_prefix, error_str);
+ return -1;
}
- } else {
+ }
+ else {
/* Normal Property (not an array) */
/* see if we can coorce into a python type - PropertyType */
@@ -862,7 +777,7 @@ static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self )
if (RNA_property_type(self->prop) == PROP_COLLECTION) {
len = RNA_property_collection_length(&self->ptr, self->prop);
} else {
- len = RNA_property_array_length(self->prop);
+ len = RNA_property_array_length(&self->ptr, self->prop);
if (len==0) { /* not an array*/
PyErr_SetString(PyExc_AttributeError, "len() only available for collection RNA types");
@@ -888,7 +803,7 @@ static PyObject *prop_subscript_collection_int(BPy_PropertyRNA * self, int keynu
}
static PyObject *prop_subscript_array_int(BPy_PropertyRNA * self, int keynum)
{
- int len= RNA_property_array_length(self->prop);
+ int len= RNA_property_array_length(&self->ptr, self->prop);
if(keynum < 0) keynum += len;
@@ -993,7 +908,7 @@ static PyObject *prop_subscript_array(BPy_PropertyRNA * self, PyObject *key)
return prop_subscript_array_int(self, PyLong_AsSsize_t(key));
}
else if (PySlice_Check(key)) {
- int len= RNA_property_array_length(self->prop);
+ int len= RNA_property_array_length(&self->ptr, self->prop);
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0)
@@ -1020,7 +935,7 @@ static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key )
{
if (RNA_property_type(self->prop) == PROP_COLLECTION) {
return prop_subscript_collection(self, key);
- } else if (RNA_property_array_length(self->prop)) { /* arrays are currently fixed length, zero length means its not an array */
+ } else if (RNA_property_array_length(&self->ptr, self->prop)) { /* arrays are currently fixed length, zero length means its not an array */
return prop_subscript_array(self, key);
} else {
PyErr_SetString(PyExc_TypeError, "rna type is not an array or a collection");
@@ -1049,7 +964,7 @@ static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int
static int prop_subscript_ass_array_int(BPy_PropertyRNA * self, int keynum, PyObject *value)
{
- int len= RNA_property_array_length(self->prop);
+ int len= RNA_property_array_length(&self->ptr, self->prop);
if(keynum < 0) keynum += len;
@@ -1083,7 +998,7 @@ static int pyrna_prop_ass_subscript( BPy_PropertyRNA * self, PyObject *key, PyOb
return prop_subscript_ass_array_int(self, i, value);
}
else if (PySlice_Check(key)) {
- int len= RNA_property_array_length(self->prop);
+ int len= RNA_property_array_length(&self->ptr, self->prop);
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0)
@@ -1496,7 +1411,7 @@ static void foreach_attr_type( BPy_PropertyRNA *self, char *attr,
RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) {
prop = RNA_struct_find_property(&itemptr, attr);
*raw_type= RNA_property_raw_type(prop);
- *attr_tot = RNA_property_array_length(prop);
+ *attr_tot = RNA_property_array_length(&itemptr, prop);
*attr_signed= (RNA_property_subtype(prop)==PROP_UNSIGNED) ? FALSE:TRUE;
break;
}
@@ -1535,7 +1450,7 @@ static int foreach_parse_args(
if (RNA_property_type(self->prop) == PROP_COLLECTION)
array_tot = RNA_property_collection_length(&self->ptr, self->prop);
else
- array_tot = RNA_property_array_length(self->prop);
+ array_tot = RNA_property_array_length(&self->ptr, self->prop);
target_tot= array_tot * (*attr_tot);
@@ -1728,7 +1643,7 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self)
if (ret==NULL) {
/* collection did not work, try array */
- int len = RNA_property_array_length(self->prop);
+ int len = RNA_property_array_length(&self->ptr, self->prop);
if (len) {
int i;
@@ -1819,7 +1734,7 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
{
PyObject *ret;
int type = RNA_property_type(prop);
- int len = RNA_property_array_length(prop);
+ int len = RNA_property_array_length(ptr, prop);
int a;
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index 1b8d69bc511..d65849ad8a4 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -91,4 +91,9 @@ PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *args);
void pyrna_alloc_types(void);
void pyrna_free_types(void);
+/* primitive type conversion */
+int pyrna_py_to_boolean_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, char *error_str, int error_str_size);
+int pyrna_py_to_int_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, char *error_str, int error_str_size);
+int pyrna_py_to_float_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, char *error_str, int error_str_size);
+
#endif