Implemented dynamic and multidimensional array support in RNA.
authorArystanbek Dyussenov <arystan.d@gmail.com>
Tue, 25 Aug 2009 17:06:36 +0000 (17:06 +0000)
committerArystanbek Dyussenov <arystan.d@gmail.com>
Tue, 25 Aug 2009 17:06:36 +0000 (17:06 +0000)
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]

24 files changed:
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/fcurve.c
source/blender/editors/animation/anim_ipo_utils.c
source/blender/editors/animation/drivers.c
source/blender/editors/animation/keyframing.c
source/blender/editors/animation/keyingsets.c
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_anim.c
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_utils.c
source/blender/editors/space_outliner/outliner.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/RNA_define.h
source/blender/makesrna/RNA_types.h
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_define.c
source/blender/makesrna/intern/rna_internal_types.h
source/blender/makesrna/intern/rna_mesh.c
source/blender/makesrna/intern/rna_object.c
source/blender/python/intern/bpy_array.c [new file with mode: 0644]
source/blender/python/intern/bpy_rna.c
source/blender/python/intern/bpy_rna.h

index 44d73a7f5b47d48fd1e7b327e91c20f9337574b7..df7004d3f6b424837598c5146d83cd5b2e18bc90 100644 (file)
@@ -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);
index 90bf08059d766aabd5d81bcce9a67f71846d423f..31f6e2c606727d8b70cbf1957cf466fffe632999 100644 (file)
@@ -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);
index ecf0bdbf285e317810ff384602aa3a903a589c63..26edf930f0b85fcdb8f0f318f934fe8faae63a44 100644 (file)
@@ -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) */
index 849e2d2eede18b0d902bf353358c19d221de8a49..e7b7d785d7bf84c8ac52789a3e2caf01acc5eb57 100644 (file)
@@ -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;
index b62c69c7b38edbfa26358032b01377be7bce1179..dc73011549c2d7b3db6e5f4ee78352ba7d29bff3 100644 (file)
@@ -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;
index d22fe763ad48baad48485938c33bdb296f402ecb..21f969467aa0488db4de4e33f6b68669a454a5a9 100644 (file)
@@ -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 
index 9bd6c2577ff665d376d67b60a67bf4999f48ab49..3c6e12905d6983980694ee755b2931eaaa226940 100644 (file)
@@ -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;
index 2993a1aba156dd16f9604f1c1bf6caec45a8391f..784d820ea52868eec548bdd364bfe6af7bb19109 100644 (file)
@@ -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) {
index 3b4471bd4b95cc0dfffbd19833a8647823f435b4..a52afcb1a92523876f522c191814083b96344c01 100644 (file)
@@ -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);
index 56badedaded14b6105cb4344704390cce23282f5..4cfc44e56c8c01585cacb73f9e89a1b2b6461d75 100644 (file)
@@ -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);
        
index 997ac8b78c64dcc43ccd1d5e95553874ed5d7804..5b44f6544d1cf92ff089e5b7172355080e0eb684 100644 (file)
@@ -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);
index 762ad82344b749fa780babc4864699633412601e..d564573a5439de6481ebf4def6ab53ff0628e156 100644 (file)
@@ -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;
                }
index fb351efed668b538dd18f9fd088704c1f720c161..cb54fe2ad8d21021ba54cc74b8de3eb4caed6b48 100644 (file)
@@ -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);
 
index 33f5d7137b831f55ab6aaad60354f0420e955d22..1c6837bbcc81083eeabe77ea3c987e5368cb2397 100644 (file)
@@ -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);
index 042f7578cf4cf303c652b04fa95ce581fbd79fe3..1acbfb21385400c1292f60aa642eea6a89744267 100644 (file)
@@ -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 {
index fa3a5a406860b1c6e82844f17366e95f765bc43f..0c90a28a0e92f5200103e493621310b9d3d5e556 100644 (file)
@@ -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);
index c2f1f31a4bc0d6869f6a02789652b7295418dca4..e71dcc2a586148eebf1d1005a16087eb2b36675d 100644 (file)
@@ -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) {
index 3b0db9493501ff595026838459312e057ad03baf..1f51b3ff34c1005a362883eba62b9bcd0880691e 100644 (file)
@@ -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:
index 12bd876ce52491fd26c5ba91d88a89f4575b504d..d706fd5ac1953aa055408e4113a33622331bc173 100644 (file)
@@ -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;
index 84190d60d1105870c88f26138e88f03b23f66524..4d53986be4f4470ecaf91612bc958c5d83878361 100644 (file)
@@ -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)
index bad36025edacb7fd72cb749a73174f5474197ef7..f0b055bd0e89f1768ade23d4c8015a77501f67a2 100644 (file)
@@ -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 (file)
index 0000000..d52bfda
--- /dev/null
@@ -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);
+}
index 70ff8e48084f53197d14e42dd94ae5c9501c7c9b..3902a9fd9b5f6778ac427027a685e136c58a99ae 100644 (file)
@@ -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;
 
index 1b8d69bc5110d73f7c5b96c24249d78c6fa962ec..d65849ad8a4f78ecdfc3e6d742291b72d499da4e 100644 (file)
@@ -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