diff options
author | Elia Sarti <vekoon@gmail.com> | 2010-01-24 13:51:59 +0300 |
---|---|---|
committer | Elia Sarti <vekoon@gmail.com> | 2010-01-24 13:51:59 +0300 |
commit | 9733e902a51e5b6ea42ea9ff28569b36ce9a307e (patch) | |
tree | 114e4c2038fe24b6747a6d387f1e99ec5cbb5143 /source/blender/makesrna/intern | |
parent | 7c21eb7cd560fc62807ad8182a7b10635bc7d845 (diff) |
RNA functions
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).
Diffstat (limited to 'source/blender/makesrna/intern')
-rw-r--r-- | source/blender/makesrna/intern/makesrna.c | 121 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 61 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_action_api.c | 19 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_define.c | 30 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_internal.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_object_api.c | 6 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_rna.c | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene_api.c | 2 |
8 files changed, 174 insertions, 68 deletions
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index fe9caf26e1b..978ca0ba188 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -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"); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 1fdbb3f9a15..cb3911b6423 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -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; } diff --git a/source/blender/makesrna/intern/rna_action_api.c b/source/blender/makesrna/intern/rna_action_api.c index 991a8251cc5..f1f3800db42 100644 --- a/source/blender/makesrna/intern/rna_action_api.c +++ b/source/blender/makesrna/intern/rna_action_api.c @@ -41,40 +41,35 @@ #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 diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index ed10c0819fd..d2036c61f61 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -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) diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 3d18804036a..5423c3eee31 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -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 */ diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 8379ae7995d..6b62a8c7a0b 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -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 */ diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 51f0fe62722..d917d553fed 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -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) diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 84dc3e6971e..cd23330557e 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -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 |