RNA functions
authorElia Sarti <vekoon@gmail.com>
Sun, 24 Jan 2010 10:51:59 +0000 (10:51 +0000)
committerElia Sarti <vekoon@gmail.com>
Sun, 24 Jan 2010 10:51:59 +0000 (10:51 +0000)
Fixed and completed support for returning multiple values. This includes support for returning arrays, both fixed and dynamically sized. The way this is achieved is by storing an additional int value next to the dynamic parameter in the ParameterList stack which gets passed to the C function as an additional parameter. In the case of return parameters it is duty of the C function to set this int to the correct length value for the dynamic parameter (which makes sense). Note that for the dynamic output/return parameter it is assumed the function has allocated that memory (which gets freed automatically).

Also, I cleaned the makesrna's bridge function generation code a bit and renamed PROP_RETURN to PROP_OUTPUT, which represents better the reality now that there are multiple returns. The function now to mark multiple returns (outputs) is RNA_def_function_output.

For an example, look at Action.get_frame_range in rna_action_api.c, by the way Aligorith I removed the #ifdef for this function now that there's support for returning arrays, feel free to modify (the function seems to work).

14 files changed:
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_action_api.c
source/blender/makesrna/intern/rna_define.c
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_object_api.c
source/blender/makesrna/intern/rna_rna.c
source/blender/makesrna/intern/rna_scene_api.c
source/blender/python/intern/bpy_array.c
source/blender/python/intern/bpy_rna.c
source/blender/python/intern/bpy_rna.h

index 8a644b8..17d6436 100644 (file)
@@ -886,6 +886,10 @@ void RNA_parameter_get(ParameterList *parms, PropertyRNA *parm, void **value);
 void RNA_parameter_get_lookup(ParameterList *parms, const char *identifier, void **value);
 void RNA_parameter_set(ParameterList *parms, PropertyRNA *parm, void *value);
 void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, void *value);
+int RNA_parameter_length_get(ParameterList *parms, PropertyRNA *parm);
+int RNA_parameter_length_get_data(ParameterList *parms, PropertyRNA *parm, void *data);
+void RNA_parameter_length_set(ParameterList *parms, PropertyRNA *parm, int length);
+void RNA_parameter_length_set_data(ParameterList *parms, PropertyRNA *parm, void *data, int length);
 
 int RNA_function_call(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms);
 int RNA_function_call_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, const char *identifier, ParameterList *parms);
index f340834..4bdb9f0 100644 (file)
@@ -172,7 +172,7 @@ void RNA_def_property_srna(PropertyRNA *prop, const char *type);
 FunctionRNA *RNA_def_function(StructRNA *srna, const char *identifier, const char *call);
 FunctionRNA *RNA_def_function_runtime(StructRNA *srna, const char *identifier, CallFunc call);
 void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret);
-void RNA_def_function_return_mark(FunctionRNA *func, PropertyRNA *ret);
+void RNA_def_function_output(FunctionRNA *func, PropertyRNA *ret);
 void RNA_def_function_flag(FunctionRNA *func, int flag);
 void RNA_def_function_ui_description(FunctionRNA *func, const char *description);
 
index ebb0a0b..5480ebc 100644 (file)
@@ -150,7 +150,7 @@ typedef enum PropertyFlag {
 
        /* function paramater flags */
        PROP_REQUIRED = 1<<2,
-       PROP_RETURN = 1<<3,
+       PROP_OUTPUT = 1<<3,
        PROP_RNAPTR = 1<<11,
        /* registering */
        PROP_REGISTER = 1<<4,
index fe9caf2..978ca0b 100644 (file)
@@ -1290,8 +1290,9 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
        StructRNA *srna;
        FunctionRNA *func;
        PropertyDefRNA *dparm;
-       char *funcname, *ptrstr;
-       int first;
+       PropertyType type;
+       char *funcname, *ptrstr, *valstr;
+       int flag, pout, cptr, first;
 
        srna= dsrna->srna;
        func= dfunc->func;
@@ -1316,19 +1317,30 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
 
        dparm= dfunc->cont.properties.first;
        for(; dparm; dparm= dparm->next) {
-               if(dparm->prop->arraydimension)
+               type = dparm->prop->type;
+               flag = dparm->prop->flag;
+               pout = (flag & PROP_OUTPUT);
+               cptr = ((type == PROP_POINTER) && !(flag & PROP_RNAPTR));
+
+               if(dparm->prop==func->c_ret)
+                       ptrstr= cptr || dparm->prop->arraydimension ? "*" : "";
+               /* XXX only arrays and strings are allowed to be dynamic, is this checked anywhere? */
+               else if (cptr || (flag & PROP_DYNAMIC))
+                       ptrstr= pout ? "**" : "*";
+               /* fixed size arrays and RNA pointers are pre-allocated on the ParameterList stack, pass a pointer to it */
+               else if (type == PROP_POINTER || dparm->prop->arraydimension)
                        ptrstr= "*";
-               else if(dparm->prop==func->c_ret)
-                       ptrstr= ((dparm->prop->type == PROP_POINTER) && !(dparm->prop->flag & PROP_RNAPTR))? "*": "";
-               else if ((dparm->prop->flag & PROP_RETURN)) {
-                       if ((dparm->prop->flag & PROP_THICK_WRAP) && (dparm->prop->type == PROP_STRING))
-                               ptrstr= "";
-                       else
-                               ptrstr= ((dparm->prop->type == PROP_POINTER) && !(dparm->prop->flag & PROP_RNAPTR))? "**": "*";
-               } else
-                       ptrstr= (dparm->prop->type == PROP_POINTER)? "*": "";
+               /* PROP_THICK_WRAP strings are pre-allocated on the ParameterList stack, but type name for string props is already char*, so leave empty */
+               else if (type == PROP_STRING && (flag & PROP_THICK_WRAP))
+                       ptrstr= "";
+               else
+                       ptrstr= pout ? "*" : "";
 
                fprintf(f, "\t%s%s %s%s;\n", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), ptrstr, dparm->prop->identifier);
+
+               /* for dynamic parameters we pass an additional int for the length of the parameter */
+               if (flag & PROP_DYNAMIC)
+                       fprintf(f, "\tint %s%s_len;\n", pout ? "*" : "", dparm->prop->identifier);
        }
 
        fprintf(f, "\tchar *_data");
@@ -1349,30 +1361,45 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
 
        dparm= dfunc->cont.properties.first;
        for(; dparm; dparm= dparm->next) {
-               if ((dparm->prop->flag & PROP_RETURN))
-                       ptrstr= "";
-               else
-                       ptrstr= "*";
+               type = dparm->prop->type;
+               flag = dparm->prop->flag;
+               pout = (flag & PROP_OUTPUT);
+               cptr = ((type == PROP_POINTER) && !(flag & PROP_RNAPTR));
 
                if(dparm->prop==func->c_ret)
                        fprintf(f, "\t_retdata= _data;\n");
-               else if(dparm->prop->arraydimension)
-                       fprintf(f, "\t%s= ((%s%s*)_data);\n", dparm->prop->identifier, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop));
-               else if(dparm->prop->type == PROP_POINTER) {
-                       if(dparm->prop->flag & PROP_RNAPTR)
-                               fprintf(f, "\t%s= ((%s%s*)_data);\n", dparm->prop->identifier, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop));
-                       else
-                               fprintf(f, "\t%s= %s((%s%s**)_data);\n", dparm->prop->identifier, ptrstr, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop));
-               }
-               else {
-                       if ((dparm->prop->flag & PROP_THICK_WRAP) && (dparm->prop->type == PROP_STRING))
-                               fprintf(f, "\t%s= %s((%s%s)_data);\n", dparm->prop->identifier, ptrstr, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop));
-                       else
-                               fprintf(f, "\t%s= %s((%s%s*)_data);\n", dparm->prop->identifier, ptrstr, rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop));
+               else  {
+                       if (cptr || (flag & PROP_DYNAMIC)) {
+                               ptrstr= "**";
+                               valstr= "*";
+                       }
+                       else if (type == PROP_POINTER || dparm->prop->arraydimension) {
+                               ptrstr= "*";
+                               valstr= "";
+                       }
+                       else if (type == PROP_STRING && (flag & PROP_THICK_WRAP)) {
+                               ptrstr= "";
+                               valstr= "";
+                       }
+                       else {
+                               ptrstr= "*";
+                               valstr= "*";
+                       }
+
+                       fprintf(f, "\t%s= ", dparm->prop->identifier);
+
+                       if (!pout)
+                               fprintf(f, "%s", valstr);
+
+                       fprintf(f, "((%s%s%s)_data);\n", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), ptrstr);
+
+                       /* this must be kept in sync with RNA_parameter_length_get_data, we could just call the function directly, but this is faster */
+                       if (flag & PROP_DYNAMIC)
+                               fprintf(f, "\t%s_len= %s((int *)(_data+%d));\n", dparm->prop->identifier, pout ? "" : "*", rna_parameter_size(dparm->prop));
                }
 
                if(dparm->next)
-                       fprintf(f, "\t_data+= %d;\n", rna_parameter_size(dparm->prop));
+                       fprintf(f, "\t_data+= %d;\n", rna_parameter_size_alloc(dparm->prop));
        }
 
        if(dfunc->call) {
@@ -1412,6 +1439,9 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
                        first= 0;
 
                        fprintf(f, "%s", dparm->prop->identifier);
+
+                       if (dparm->prop->flag & PROP_DYNAMIC)
+                               fprintf(f, ", %s_len", dparm->prop->identifier);
                }
 
                fprintf(f, ");\n");
@@ -1653,7 +1683,8 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA
        FunctionRNA *func;
        PropertyDefRNA *dparm;
        StructDefRNA *dsrna;
-       int first;
+       PropertyType type;
+       int flag, pout, cptr, first;
        char *ptrstr;
 
        dsrna= rna_find_struct_def(srna);
@@ -1706,25 +1737,33 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA
 
        /* defined parameters */
        for(dparm= dfunc->cont.properties.first; dparm; dparm= dparm->next) {
+               type = dparm->prop->type;
+               flag = dparm->prop->flag;
+               pout = (flag & PROP_OUTPUT);
+               cptr = ((type == PROP_POINTER) && !(flag & PROP_RNAPTR));
+
                if(dparm->prop==func->c_ret)
                        continue;
 
-               if(!first) fprintf(f, ", ");
-               first= 0;
-
-               if((dparm->prop->type == PROP_STRING && dparm->prop->flag & PROP_THICK_WRAP))
-                       ptrstr= "";
-               else if(dparm->prop->flag & PROP_RETURN)
+               if (cptr || (flag & PROP_DYNAMIC))
+                       ptrstr= pout ? "**" : "*";
+               else if (type == PROP_POINTER || dparm->prop->arraydimension)
                        ptrstr= "*";
-               else
+               else if (type == PROP_STRING && (flag & PROP_THICK_WRAP))
                        ptrstr= "";
+               else
+                       ptrstr= pout ? "*" : "";
 
-               if(dparm->prop->arraydimension)
+               if(!first) fprintf(f, ", ");
+               first= 0;
+
+               if(!(flag & PROP_DYNAMIC) && dparm->prop->arraydimension)
                        fprintf(f, "%s%s %s[%d]", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), dparm->prop->identifier, dparm->prop->totarraylength);
-               else if(dparm->prop->type == PROP_POINTER)
-                       fprintf(f, "%s%s *%s%s", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), (dparm->prop->flag & PROP_RNAPTR) ? "" : ptrstr, dparm->prop->identifier);
                else
                        fprintf(f, "%s%s %s%s", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), ptrstr, dparm->prop->identifier);
+
+               if (flag & PROP_DYNAMIC)
+                       fprintf(f, ", int %s%s_len", pout ? "*" : "", dparm->prop->identifier);
        }
 
        fprintf(f, ");\n");
index 1fdbb3f..cb3911b 100644 (file)
@@ -3603,7 +3603,7 @@ ParameterList *RNA_parameter_list_create(ParameterList *parms, PointerRNA *ptr,
 
        /* allocate data */
        for(parm= func->cont.properties.first; parm; parm= parm->next)
-               tot+= rna_parameter_size(parm);
+               tot+= rna_parameter_size_alloc(parm);
 
        parms->data= MEM_callocN(tot, "RNA_parameter_list_create");
        parms->func= func;
@@ -3644,7 +3644,11 @@ ParameterList *RNA_parameter_list_create(ParameterList *parms, PointerRNA *ptr,
                        }
                }
 
-               data= ((char*)data) + size;
+               /* set length to 0 */
+               if (parm->flag & PROP_DYNAMIC)
+                       *((int *)(((char *)data) + size))= 0;
+
+               data= ((char*)data) + rna_parameter_size_alloc(parm);
        }
 
        return parms;
@@ -3666,7 +3670,7 @@ void RNA_parameter_list_free(ParameterList *parms)
                                MEM_freeN(array);
                }
 
-               tot+= rna_parameter_size(parm);
+               tot+= rna_parameter_size_alloc(parm);
        }
 
        MEM_freeN(parms->data);
@@ -3692,7 +3696,7 @@ void RNA_parameter_list_begin(ParameterList *parms, ParameterIterator *iter)
        iter->offset= 0;
 
        if(iter->valid) {
-               iter->size= rna_parameter_size(iter->parm);
+               iter->size= rna_parameter_size_alloc(iter->parm);
                iter->data= (((char*)iter->parms->data)+iter->offset);
                ptype= RNA_property_type(iter->parm);
        }
@@ -3707,7 +3711,7 @@ void RNA_parameter_list_next(ParameterIterator *iter)
        iter->valid= iter->parm != NULL;
 
        if(iter->valid) {
-               iter->size= rna_parameter_size(iter->parm);
+               iter->size= rna_parameter_size_alloc(iter->parm);
                iter->data= (((char*)iter->parms->data)+iter->offset);
                ptype= RNA_property_type(iter->parm);
        }
@@ -3778,6 +3782,51 @@ void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, void
                RNA_parameter_set(parms, parm, value);
 }
 
+int RNA_parameter_length_get(ParameterList *parms, PropertyRNA *parm)
+{
+       ParameterIterator iter;
+       int len= 0;
+
+       RNA_parameter_list_begin(parms, &iter);
+
+       for(; iter.valid; RNA_parameter_list_next(&iter))
+               if(iter.parm==parm)
+                       break;
+
+       if(iter.valid)
+               len= RNA_parameter_length_get_data(parms, parm, iter.data);
+
+       RNA_parameter_list_end(&iter);
+
+       return len;
+}
+
+void RNA_parameter_length_set(ParameterList *parms, PropertyRNA *parm, int length)
+{
+       ParameterIterator iter;
+
+       RNA_parameter_list_begin(parms, &iter);
+
+       for(; iter.valid; RNA_parameter_list_next(&iter))
+               if(iter.parm==parm)
+                       break;
+
+       if(iter.valid)
+               RNA_parameter_length_set_data(parms, parm, iter.data, length);
+
+       RNA_parameter_list_end(&iter);
+}
+
+int RNA_parameter_length_get_data(ParameterList *parms, PropertyRNA *parm, void *data)
+{
+       return *((int *)(((char *)data) + rna_parameter_size(parm)));
+}
+
+void RNA_parameter_length_set_data(ParameterList *parms, PropertyRNA *parm, void *data, int length)
+{
+       *((int *)(((char *)data) + rna_parameter_size(parm)))= length;
+}
+
 int RNA_function_call(bContext *C, ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
 {
        if(func->call) {
@@ -4022,7 +4071,7 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt
                        retdata= iter.data;
                        continue;
                }
-               else if (flag & PROP_RETURN) {
+               else if (flag & PROP_OUTPUT) {
                        continue;
                }
 
index 991a825..f1f3800 100644 (file)
 #include "DNA_anim_types.h"
 #include "DNA_curve_types.h"
 
-/* XXX disabled until RNA allows returning arrays */
-#if 0
 /* return frame range of all curves (min, max) or (0, 1) if there are no keys */
-int *rna_Action_get_frame_range(bAction *act, int *ret_length)
+void rna_Action_get_frame_range(bAction *act, int **frame_range, int *length_r)
 {
        int *ret;
        float start, end;
 
        calc_action_range(act, &start, &end, 1);
 
-       *ret_length= 2;
-       ret= MEM_callocN(*ret_length * sizeof(int), "rna_Action_get_frame_range");
+       *length_r= 2;
+       ret= MEM_callocN(*length_r * sizeof(int), "rna_Action_get_frame_range");
 
        ret[0]= (int)start;
        ret[1]= (int)end;
-       
-       return ret;
+
+       *frame_range= ret;
 }
-#endif
 
 #else
 
 void RNA_api_action(StructRNA *srna)
 {
-#if 0
        FunctionRNA *func;
        PropertyRNA *parm;
 
        func= RNA_def_function(srna, "get_frame_range", "rna_Action_get_frame_range");
        RNA_def_function_ui_description(func, "Get action frame range as a (min, max) tuple.");
        parm= RNA_def_int_array(func, "frame_range", 1, NULL, 0, 0, "", "Action frame range.", 0, 0);
-       RNA_def_property_flag(parm, PROP_DYNAMIC_ARRAY);
-       RNA_def_function_return(func, parm);
-#endif
+       RNA_def_property_flag(parm, PROP_DYNAMIC);
+       RNA_def_function_output(func, parm);
 }
 
 #endif
index ed10c08..d2036c6 100644 (file)
@@ -2419,17 +2419,26 @@ FunctionRNA *RNA_def_function_runtime(StructRNA *srna, const char *identifier, C
        return func;
 }
 
-/* C return value only!, multiple rna returns can be done with RNA_def_function_return_mark */
+/* C return value only!, multiple RNA returns can be done with RNA_def_function_output */
 void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret)
 {
+       if (ret->flag & PROP_DYNAMIC) {
+               fprintf(stderr, "RNA_def_function_return: %s.%s, dynamic values are not allowed as strict returns, use RNA_def_function_output instead.\n", func->identifier, ret->identifier);
+               return;
+       }
+       else if (ret->arraydimension) {
+               fprintf(stderr, "RNA_def_function_return: %s.%s, arrays are not allowed as strict returns, use RNA_def_function_output instead.\n", func->identifier, ret->identifier);
+               return;
+       }
+
        func->c_ret= ret;
 
-       RNA_def_function_return_mark(func, ret);
+       RNA_def_function_output(func, ret);
 }
 
-void RNA_def_function_return_mark(FunctionRNA *func, PropertyRNA *ret)
+void RNA_def_function_output(FunctionRNA *func, PropertyRNA *ret)
 {
-       ret->flag|=PROP_RETURN;
+       ret->flag|= PROP_OUTPUT;
 }
 
 void RNA_def_function_flag(FunctionRNA *func, int flag)
@@ -2448,6 +2457,7 @@ int rna_parameter_size(PropertyRNA *parm)
        int len= parm->totarraylength; /* only supports fixed length at the moment */
 
        if(len > 0) {
+               /* XXX in other parts is mentioned that strings can be dynamic as well */
                if (parm->flag & PROP_DYNAMIC)
                        return sizeof(void *);
 
@@ -2497,6 +2507,18 @@ int rna_parameter_size(PropertyRNA *parm)
        return sizeof(void *);
 }
 
+/* this function returns the size of the memory allocated for the parameter,
+   useful for instance for memory alignment or for storing additional information */
+int rna_parameter_size_alloc(PropertyRNA *parm)
+{
+       int size = rna_parameter_size(parm);
+
+       if (parm->flag & PROP_DYNAMIC)
+               size+= sizeof(int);
+
+       return size;
+}
+
 /* Dynamic Enums */
 
 void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, EnumPropertyItem *item)
index 3d18804..5423c3e 100644 (file)
@@ -331,6 +331,7 @@ PointerRNA rna_pointer_inherit_refine(struct PointerRNA *ptr, struct StructRNA *
 /* Functions */
 
 int rna_parameter_size(struct PropertyRNA *parm);
+int rna_parameter_size_alloc(struct PropertyRNA *parm);
 
 #endif /* RNA_INTERNAL_H */
 
index 8379ae7..6b62a8c 100644 (file)
@@ -497,13 +497,13 @@ void RNA_api_object(StructRNA *srna)
        /* return location and normal */
        parm= RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "The hit location of this ray cast", -1e4, 1e4);
        RNA_def_property_flag(parm, PROP_THICK_WRAP);
-       RNA_def_function_return_mark(func, parm);
+       RNA_def_function_output(func, parm);
        parm= RNA_def_float_vector(func, "normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", "The face normal at the ray cast hit location", -1e4, 1e4);
        RNA_def_property_flag(parm, PROP_THICK_WRAP);
-       RNA_def_function_return_mark(func, parm);
+       RNA_def_function_output(func, parm);
        
        parm= RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when no intersection is found.", 0, 0);
-       RNA_def_function_return_mark(func, parm);
+       RNA_def_function_output(func, parm);
 
        
        /* DAG */
index 51f0fe6..d917d55 100644 (file)
@@ -439,7 +439,7 @@ static int rna_Property_readonly_get(PointerRNA *ptr)
 static int rna_Property_use_return_get(PointerRNA *ptr)
 {
        PropertyRNA *prop= (PropertyRNA*)ptr->data;
-       return prop->flag & PROP_RETURN ? 1:0;
+       return prop->flag & PROP_OUTPUT ? 1:0;
 }
 
 static int rna_Property_is_required_get(PointerRNA *ptr)
index 84dc3e6..cd23330 100644 (file)
@@ -134,7 +134,7 @@ void RNA_api_scene_render(StructRNA *srna)
        parm= RNA_def_int(func, "frame", INT_MIN, INT_MIN, INT_MAX, "", "Frame number to use, if unset the current frame will be used.", MINAFRAME, MAXFRAME);
        parm= RNA_def_string(func, "name", "", FILE_MAX, "File Name", "the resulting filename from the scenes render settings.");
        RNA_def_property_flag(parm, PROP_THICK_WRAP); /* needed for string return value */
-       RNA_def_function_return_mark(func, parm);
+       RNA_def_function_output(func, parm);
 }
 
 #endif
index 5afcae8..e401ea5 100644 (file)
@@ -242,7 +242,7 @@ static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int
        return data;
 }
 
-static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
+static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
 {
        int totdim, dim_size[MAX_ARRAY_DIMENSION];
        int totitem;
@@ -266,6 +266,8 @@ static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *p
                        if (RNA_property_flag(prop) & PROP_DYNAMIC) {
                                /* not freeing allocated mem, RNA_parameter_list_free will do this */
                                *(char**)param_data= data;
+
+                               RNA_parameter_length_set_data(parms, prop, param_data, totitem);
                        }
                }
                else {
@@ -358,18 +360,18 @@ static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *
        RNA_property_boolean_set_index(ptr, prop, index, *(int*)value);
 }
 
-int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix)
+int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, char *param_data, PyObject *py, const char *error_prefix)
 {
        int ret;
        switch (RNA_property_type(prop)) {
        case PROP_FLOAT:
-               ret= py_to_array(py, ptr, prop, param_data, py_float_check, "float", sizeof(float), py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix);
+               ret= py_to_array(py, ptr, prop, parms, param_data, py_float_check, "float", sizeof(float), py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix);
                break;
        case PROP_INT:
-               ret= py_to_array(py, ptr, prop, param_data, py_int_check, "int", sizeof(int), py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix);
+               ret= py_to_array(py, ptr, prop, parms, param_data, py_int_check, "int", sizeof(int), py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix);
                break;
        case PROP_BOOLEAN:
-               ret= py_to_array(py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(int), py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix);
+               ret= py_to_array(py, ptr, prop, parms, param_data, py_bool_check, "boolean", sizeof(int), py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix);
                break;
        default:
                PyErr_SetString(PyExc_TypeError, "not an array type");
index 49de1b3..f359dd9 100644 (file)
@@ -593,7 +593,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha
                                break;
                        }
                } else {
-                       if (pyrna_py_to_prop(ptr, prop, NULL, item, error_prefix)) {
+                       if (pyrna_py_to_prop(ptr, prop, NULL, NULL, item, error_prefix)) {
                                error_val= -1;
                                break;
                        }
@@ -647,7 +647,7 @@ static PyObject *pyrna_func_to_py(BPy_DummyPointerRNA *pyrna, FunctionRNA *func)
 
 
 
-int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix)
+int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, void *data, PyObject *value, const char *error_prefix)
 {
        /* XXX hard limits should be checked here */
        int type = RNA_property_type(prop);
@@ -670,7 +670,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
                        return -1;
                }
                /* done getting the length */
-               ok= pyrna_py_to_array(ptr, prop, data, value, error_prefix);
+               ok= pyrna_py_to_array(ptr, prop, parms, data, value, error_prefix);
 
                if (!ok) {
                        /* PyErr_Format(PyExc_AttributeError, "%.200s %s", error_prefix, error_str); */
@@ -688,7 +688,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v
                        /* prefer not to have an exception here
                         * however so many poll functions return None or a valid Object.
                         * its a hassle to convert these into a bool before returning, */
-                       if(RNA_property_flag(prop) & PROP_RETURN)
+                       if(RNA_property_flag(prop) & PROP_OUTPUT)
                                param = PyObject_IsTrue( value );
                        else
                                param = PyLong_AsSsize_t( value );
@@ -1990,7 +1990,7 @@ static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObjec
        }
                
        /* pyrna_py_to_prop sets its own exceptions */
-       return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "StructRNA - item.attr = val:");
+       return pyrna_py_to_prop(&self->ptr, prop, NULL, NULL, value, "StructRNA - item.attr = val:");
 }
 
 static PyObject *pyrna_prop_dir(BPy_PropertyRNA *self)
@@ -2066,7 +2066,7 @@ static int pyrna_prop_setattro( BPy_PropertyRNA *self, PyObject *pyname, PyObjec
                if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) {
                        if ((prop = RNA_struct_find_property(&r_ptr, name))) {
                                /* pyrna_py_to_prop sets its own exceptions */
-                               return pyrna_py_to_prop(&r_ptr, prop, NULL, value, "BPy_PropertyRNA - Attribute (setattr):");
+                               return pyrna_py_to_prop(&r_ptr, prop, NULL, NULL, value, "BPy_PropertyRNA - Attribute (setattr):");
                        }
                }
        }
@@ -2634,7 +2634,7 @@ static PyObject * pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *k
        }
 }
 
-PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
+PyObject *pyrna_param_to_py(PointerRNA *ptr, ParameterList *parms, PropertyRNA *prop, void *data)
 {
        PyObject *ret;
        int type = RNA_property_type(prop);
@@ -2642,7 +2642,15 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data)
        int a;
 
        if(RNA_property_array_check(ptr, prop)) {
-               int len = RNA_property_array_length(ptr, prop);
+               int len;
+
+               if (flag & PROP_DYNAMIC) {
+                       len= RNA_parameter_length_get_data(parms, prop, data);
+
+                       data= *((void **)data);
+               }
+               else
+                       len= RNA_property_array_length(ptr, prop);
 
                /* resolve the array from a new pytype */
 
@@ -2819,7 +2827,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
                flag= RNA_property_flag(parm);
 
                /* only useful for single argument returns, we'll need another list loop for multiple */
-               if (flag & PROP_RETURN) {
+               if (flag & PROP_OUTPUT) {
                        ret_len++;
                        if (pret_single==NULL) {
                                pret_single= parm;
@@ -2856,7 +2864,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
                                continue;
                }
 
-               err= pyrna_py_to_prop(&funcptr, parm, iter.data, item, "");
+               err= pyrna_py_to_prop(&funcptr, parm, &parms, iter.data, item, "");
 
                if(err!=0) {
                        /* the error generated isnt that useful, so generate it again with a useful prefix
@@ -2869,7 +2877,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
                        else
                                snprintf(error_prefix, sizeof(error_prefix), "%s.%s(): error with argument %d, \"%s\" - ", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), i, parm_id);
 
-                       pyrna_py_to_prop(&funcptr, parm, iter.data, item, error_prefix);
+                       pyrna_py_to_prop(&funcptr, parm, &parms, iter.data, item, error_prefix);
 
                        break;
                }
@@ -2927,7 +2935,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
                RNA_parameter_list_begin(&parms, &iter);
                for(; iter.valid; RNA_parameter_list_next(&iter)) {
                        parm= iter.parm;
-                       if(RNA_property_flag(parm) & PROP_RETURN)
+                       if(RNA_property_flag(parm) & PROP_OUTPUT)
                                continue;
 
                        BLI_dynstr_appendf(good_args, first ? "%s" : ", %s", RNA_property_identifier(parm));
@@ -2974,14 +2982,14 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw)
                                                parm= iter.parm;
                                                flag= RNA_property_flag(parm);
 
-                                               if (flag & PROP_RETURN)
-                                                       PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data));
+                                               if (flag & PROP_OUTPUT)
+                                                       PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, &parms, parm, iter.data));
                                        }
 
                                        RNA_parameter_list_end(&iter);
                                }
                                else
-                                       ret= pyrna_param_to_py(&funcptr, pret_single, retdata_single);
+                                       ret= pyrna_param_to_py(&funcptr, &parms, pret_single, retdata_single);
 
                                /* possible there is an error in conversion */
                                if(ret==NULL)
@@ -3724,7 +3732,7 @@ static int rna_function_arg_count(FunctionRNA *func)
 
        for(link=lb->first; link; link=link->next) {
                parm= (PropertyRNA*)link;
-               if(!(RNA_property_flag(parm) & PROP_RETURN))
+               if(!(RNA_property_flag(parm) & PROP_OUTPUT))
                        count++;
        }
        
@@ -3825,7 +3833,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
                        if(strcmp(identifier, rna_attr) == 0) { \
                                item= PyObject_GetAttrString(py_class, py_attr); \
                                if(item && item != Py_None) { \
-                                       if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0) { \
+                                       if(pyrna_py_to_prop(dummyptr, prop, NULL, NULL, item, "validating class error:") != 0) { \
                                                Py_DECREF(item); \
                                                return -1; \
                                        } \
@@ -3849,7 +3857,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun
                else {
                        Py_DECREF(item); /* no need to keep a ref, the class owns it */
 
-                       if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0)
+                       if(pyrna_py_to_prop(dummyptr, prop, NULL, NULL, item, "validating class error:") != 0)
                                return -1;
                }
        }
@@ -3912,7 +3920,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
                                flag= RNA_property_flag(parm);
 
                                /* only useful for single argument returns, we'll need another list loop for multiple */
-                               if (flag & PROP_RETURN) {
+                               if (flag & PROP_OUTPUT) {
                                        ret_len++;
                                        if (pret_single==NULL) {
                                                pret_single= parm;
@@ -3922,7 +3930,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
                                        continue;
                                }
 
-                               parmitem= pyrna_param_to_py(&funcptr, parm, iter.data);
+                               parmitem= pyrna_param_to_py(&funcptr, parms, parm, iter.data);
                                PyTuple_SET_ITEM(args, i, parmitem);
                                i++;
                        }
@@ -3950,7 +3958,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
        }
        else {
                if(ret_len==1) {
-                       err= pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, "calling class function:");
+                       err= pyrna_py_to_prop(&funcptr, pret_single, parms, retdata_single, ret, "calling class function:");
                }
                else if (ret_len > 1) {
 
@@ -3972,8 +3980,8 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
                                        flag= RNA_property_flag(parm);
 
                                        /* only useful for single argument returns, we'll need another list loop for multiple */
-                                       if (flag & PROP_RETURN) {
-                                               err= pyrna_py_to_prop(&funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:");
+                                       if (flag & PROP_OUTPUT) {
+                                               err= pyrna_py_to_prop(&funcptr, parm, parms, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:");
                                                if(err)
                                                        break;
                                        }
index f7afeed..284eef2 100644 (file)
@@ -75,7 +75,7 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr );
 PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop );
 
 /* operators also need this to set args */
-int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix);
+int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, void *data, PyObject *value, const char *error_prefix);
 int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const char *error_prefix);
 PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop);
 
@@ -92,7 +92,7 @@ void pyrna_alloc_types(void);
 void pyrna_free_types(void);
 
 /* primitive type conversion */
-int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix);
+int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, char *param_data, PyObject *py, const char *error_prefix);
 int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix);
 
 PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop);