diff options
author | Arystanbek Dyussenov <arystan.d@gmail.com> | 2009-08-25 21:06:36 +0400 |
---|---|---|
committer | Arystanbek Dyussenov <arystan.d@gmail.com> | 2009-08-25 21:06:36 +0400 |
commit | 706a4c22b54ede250fbdb2c2bd772c63cdbf7d09 (patch) | |
tree | e9398918b950b98e3fa17741d67fe7b94915f89f /source/blender | |
parent | 7288bacad9bbe5e670de3454c9a64dee0c3d920c (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]
Diffstat (limited to 'source/blender')
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 |