diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-04-07 04:49:39 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-04-07 04:49:39 +0400 |
commit | 767db1b71674efb599f03b5892c32d207647acd3 (patch) | |
tree | fc64129bea43fe563bc0ad1448e17405e1b04bb0 /source/blender/python | |
parent | 88ab62c03189a04f6a74b040ad269e5a901c4af1 (diff) |
RNA: Commit of the API patch by vekoon. This adds Functions to RNA,
which can be defined to call C functions with defined parameters.
* Parameters are RNA properties, with the same types.
* Parameters are stored in a ParameterList, which is like a small
stack with the values. This is then used to call the C function.
* Includes Python integration.
* Only one test function is part of this commit, ID.rename.
* Integration with the editors/ module is not included in this
commit, there's some issues to be worked out for that still.
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 556 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 16 |
2 files changed, 554 insertions, 18 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 20ca134c67e..b30616ba035 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -24,6 +24,7 @@ #include "bpy_rna.h" #include "bpy_compat.h" +#include "bpy_util.h" //#include "blendef.h" #include "BLI_dynstr.h" #include "BLI_listbase.h" @@ -45,6 +46,11 @@ static int pyrna_prop_compare( BPy_PropertyRNA * a, BPy_PropertyRNA * b ) return (a->prop==b->prop && a->ptr.data==b->ptr.data ) ? 0 : -1; } +static int pyrna_func_compare( BPy_FunctionRNA * a, BPy_FunctionRNA * b ) +{ + return (a->func==b->func && a->ptr.data==b->ptr.data ) ? 0 : -1; +} + /* For some reason python3 needs these :/ */ static PyObject *pyrna_struct_richcmp(BPy_StructRNA * a, BPy_StructRNA * b, int op) @@ -67,6 +73,16 @@ static PyObject *pyrna_prop_richcmp(BPy_PropertyRNA * a, BPy_PropertyRNA * b, in return Py_CmpToRich(op, cmp_result); } +static PyObject *pyrna_func_richcmp(BPy_FunctionRNA * a, BPy_FunctionRNA * b, int op) +{ + int cmp_result= -1; /* assume false */ + if (BPy_FunctionRNA_Check(a) && BPy_FunctionRNA_Check(b)) { + cmp_result= pyrna_func_compare(a, b); + } + + return Py_CmpToRich(op, cmp_result); +} + /*----------------------repr--------------------------------------------*/ static PyObject *pyrna_struct_repr( BPy_StructRNA * self ) { @@ -105,6 +121,11 @@ static PyObject *pyrna_prop_repr( BPy_PropertyRNA * self ) return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(&self->ptr), RNA_property_identifier(&self->ptr, self->prop)); } +static PyObject *pyrna_func_repr( BPy_FunctionRNA * self ) +{ + return PyUnicode_FromFormat( "[BPy_FunctionRNA \"%s\"]", RNA_function_identifier(&self->ptr, self->func)); +} + static long pyrna_struct_hash( BPy_StructRNA * self ) { return (long)self->ptr.data; @@ -124,13 +145,22 @@ static void pyrna_struct_dealloc( BPy_StructRNA * self ) return; } +/* use our own dealloc so we can free a property if we use one */ +static void pyrna_function_dealloc( BPy_FunctionRNA * self ) +{ + if (Py_TYPE(self)->tp_free) + Py_TYPE(self)->tp_free(self); + + return; +} + static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) { const EnumPropertyItem *item; - int totitem, i; + int totitem; RNA_property_enum_items(ptr, prop, &item, &totitem); - return BPy_enum_as_string(item); + return (char*)BPy_enum_as_string((EnumPropertyItem*)item); } PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) @@ -201,6 +231,10 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) return ret; } +PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func) +{ + return pyrna_func_CreatePyObject(ptr, func); +} int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) { @@ -401,7 +435,6 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) return 0; } - static PyObject * pyrna_prop_to_py_index(PointerRNA *ptr, PropertyRNA *prop, int index) { PyObject *ret; @@ -661,6 +694,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname ) char *name = _PyUnicode_AsString(pyname); PyObject *ret; PropertyRNA *prop; + FunctionRNA *func; /* Include this incase this instance is a subtype of a python class * In these instances we may want to return a function or variable provided by the subtype @@ -671,13 +705,14 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname ) if (ret) return ret; else PyErr_Clear(); /* done with subtypes */ - - prop = RNA_struct_find_property(&self->ptr, name); - if (prop) { - ret = pyrna_prop_to_py(&self->ptr, prop); + if ((prop = RNA_struct_find_property(&self->ptr, name))) { + ret = pyrna_prop_to_py(&self->ptr, prop); + } + else if ((func = RNA_struct_find_function(&self->ptr, name))) { + ret = pyrna_func_to_py(&self->ptr, func); } - else if (/*self->ptr.type == &RNA_Context*/0) { + else if (self->ptr.type == &RNA_Context) { PointerRNA newptr; ListBase newlb; @@ -918,6 +953,393 @@ static PyObject * pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *k } } +/* only needed for subtyping, so a new class gets a valid BPy_FunctionRNA +* todo - also accept useful args */ +static PyObject * pyrna_func_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + + BPy_FunctionRNA *base = NULL; + + if (!PyArg_ParseTuple(args, "O!:Base BPy_FunctionRNA", &pyrna_func_Type, &base)) + return NULL; + + if (type == &pyrna_func_Type) { + return pyrna_func_CreatePyObject(&base->ptr, base->func); + } else { + BPy_FunctionRNA *ret = (BPy_FunctionRNA *) type->tp_alloc(type, 0); + ret->ptr = base->ptr; + ret->func = base->func; + return (PyObject *)ret; + } +} + +int pyrna_py_to_param(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value) +{ + /* XXX hard limits should be checked here */ + int type = RNA_property_type(ptr, prop); + int len = RNA_property_array_length(ptr, prop); + + if (len > 0) { + PyObject *item; + int i; + + if (!PySequence_Check(value)) { + PyErr_SetString(PyExc_TypeError, "expected a python sequence type assigned to an RNA array."); + return -1; + } + + if ((int)PySequence_Length(value) != len) { + PyErr_SetString(PyExc_AttributeError, "python sequence length did not match the RNA array."); + return -1; + } + + /* for arrays we have a limited number of types */ + switch (type) { + case PROP_BOOLEAN: + { + int *param_arr = (int*)data; + + /* 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) { + PyErr_SetString(PyExc_AttributeError, "one or more of the values in the sequence is not a boolean"); + return -1; + } + } + + break; + } + case PROP_INT: + { + int *param_arr = (int*)data; + + /* 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()) { + PyErr_SetString(PyExc_AttributeError, "one or more of the values in the sequence could not be used as an int"); + return -1; + } + + break; + } + case PROP_FLOAT: + { + float *param_arr = (float*)data; + + /* 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()) { + PyErr_SetString(PyExc_AttributeError, "one or more of the values in the sequence could not be used as a float"); + return -1; + } + + break; + } + } + } else { + /* Normal Property (not an array) */ + + /* see if we can coorce into a python type - PropertyType */ + switch (type) { + case PROP_BOOLEAN: + { + int param = PyObject_IsTrue( value ); + + if( param < 0 ) { + PyErr_SetString(PyExc_TypeError, "expected True/False or 0/1"); + return -1; + } else { + *((int*)data)= param; + } + break; + } + case PROP_INT: + { + int param = PyLong_AsSsize_t(value); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected an int type"); + return -1; + } else { + *((int*)data)= param; + } + break; + } + case PROP_FLOAT: + { + float param = PyFloat_AsDouble(value); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected a float type"); + return -1; + } else { + *((float*)data)= param; + } + break; + } + case PROP_STRING: + { + char *param = _PyUnicode_AsString(value); + + if (param==NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string type"); + return -1; + } else { + *((char**)data)= param; + } + break; + } + case PROP_ENUM: + { + char *param = _PyUnicode_AsString(value); + + if (param==NULL) { + char *enum_str= pyrna_enum_as_string(ptr, prop); + PyErr_Format(PyExc_TypeError, "expected a string enum type in (%s)", enum_str); + MEM_freeN(enum_str); + return -1; + } else { + int val; + if (RNA_property_enum_value(ptr, prop, param, &val)) { + *((int*)data)= val; + } else { + char *enum_str= pyrna_enum_as_string(ptr, prop); + PyErr_Format(PyExc_AttributeError, "enum \"%s\" not found in (%s)", param, enum_str); + MEM_freeN(enum_str); + return -1; + } + } + + break; + } + case PROP_POINTER: + { + StructRNA *ptype= RNA_property_pointer_type(ptr, prop); + + if(!BPy_StructRNA_Check(value)) { + PointerRNA tmp; + RNA_pointer_create(NULL, ptype, NULL, &tmp); + PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(&tmp)); + return -1; + } else { + BPy_StructRNA *param= (BPy_StructRNA*)value; + + if(ptype == &RNA_AnyType) { + *((PointerRNA*)data)= param->ptr; + } + else if(RNA_struct_is_a(¶m->ptr, ptype)) { + *((void**)data)= param->ptr.data; + } else { + PointerRNA tmp; + RNA_pointer_create(NULL, ptype, NULL, &tmp); + PyErr_Format(PyExc_TypeError, "expected a %s type", RNA_struct_identifier(&tmp)); + return -1; + } + } + break; + } + case PROP_COLLECTION: + PyErr_SetString(PyExc_AttributeError, "cant pass collections yet"); + return -1; + break; + default: + PyErr_SetString(PyExc_AttributeError, "unknown property type (pyrna_py_to_param)"); + return -1; + break; + } + } + + return 0; +} + +PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) +{ + PyObject *ret; + int type = RNA_property_type(ptr, prop); + int len = RNA_property_array_length(ptr, prop); + int a; + + if(len > 0) { + /* resolve the array from a new pytype */ + ret = PyTuple_New(len); + + switch (type) { + case PROP_BOOLEAN: + for(a=0; a<len; a++) + PyTuple_SET_ITEM(ret, a, PyBool_FromLong( ((int*)data)[a] )); + break; + case PROP_INT: + for(a=0; a<len; a++) + PyTuple_SET_ITEM(ret, a, PyLong_FromSsize_t( (Py_ssize_t)((int*)data)[a] )); + break; + case PROP_FLOAT: + for(a=0; a<len; a++) + PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble( ((float*)data)[a] )); + break; + default: + PyErr_Format(PyExc_AttributeError, "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", type); + ret = NULL; + break; + } + } + else { + /* see if we can coorce into a python type - PropertyType */ + switch (type) { + case PROP_BOOLEAN: + ret = PyBool_FromLong( *(int*)data ); + break; + case PROP_INT: + ret = PyLong_FromSsize_t( (Py_ssize_t)*(int*)data ); + break; + case PROP_FLOAT: + ret = PyFloat_FromDouble( *(float*)data ); + break; + case PROP_STRING: + { + ret = PyUnicode_FromString( *(char**)data ); + break; + } + case PROP_ENUM: + { + const char *identifier; + int val = *(int*)data; + + if (RNA_property_enum_identifier(ptr, prop, val, &identifier)) { + ret = PyUnicode_FromString( identifier ); + } else { + PyErr_Format(PyExc_AttributeError, "RNA Error: Current value \"%d\" matches no enum", val); + ret = NULL; + } + + break; + } + case PROP_POINTER: + { + PointerRNA newptr; + StructRNA *type= RNA_property_pointer_type(ptr, prop); + + if(type == &RNA_AnyType) { + /* in this case we get the full ptr */ + newptr= *(PointerRNA*)data; + } + else { + /* XXX this is missing the ID part! */ + RNA_pointer_create(NULL, type, *(void**)data, &newptr); + } + + if (newptr.data) { + ret = pyrna_struct_CreatePyObject(&newptr); + } else { + ret = Py_None; + Py_INCREF(ret); + } + break; + } + case PROP_COLLECTION: + /* XXX not supported yet + * ret = pyrna_prop_CreatePyObject(ptr, prop); */ + break; + default: + PyErr_Format(PyExc_AttributeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type); + ret = NULL; + break; + } + } + + return ret; +} + +static PyObject * pyrna_func_call(BPy_FunctionRNA * self, PyObject *args, PyObject *kw) +{ + PointerRNA funcptr; + ParameterList *parms; + ParameterIterator iter; + PropertyRNA *pret, *parm; + PyObject *ret, *item; + int i, tlen, err= 0; + const char *tid, *fid, *pid; + void *retdata= NULL; + + /* setup */ + RNA_pointer_create(NULL, &RNA_Function, self->func, &funcptr); + + pret= RNA_function_return(&self->ptr, self->func); + tlen= PyTuple_GET_SIZE(args); + + parms= RNA_parameter_list_create(&self->ptr, self->func); + RNA_parameter_list_begin(parms, &iter); + + /* parse function parameters */ + for (i= 0; iter.valid; RNA_parameter_list_next(&iter), i++) { + parm= iter.parm; + + if (parm==pret) { + retdata= iter.data; + continue; + } + + pid= RNA_property_identifier(&funcptr, parm); + item= NULL; + + if (i < tlen) + item= PyTuple_GET_ITEM(args, i); + + if (kw != NULL) + item= PyDict_GetItemString(kw, pid); + + if (item==NULL) { + /* XXX need to add flag for optional required parameters + if (flag & PARAM_OPTIONAL) + continue; */ + + tid= RNA_struct_identifier(&self->ptr); + fid= RNA_function_identifier(&self->ptr, self->func); + + PyErr_Format(PyExc_AttributeError, "%s.%s(): required parameter \"%s\" not specified", tid, fid, pid); + err= -1; + break; + } + + err= pyrna_py_to_param(&funcptr, parm, iter.data, item); + + if(err!=0) + break; + } + + ret= NULL; + if (err==0) { + /* call function */ + RNA_function_call(&self->ptr, self->func, parms); + + /* return value */ + if(pret) + ret= pyrna_param_to_py(&funcptr, pret, retdata); + } + + /* cleanup */ + RNA_parameter_list_end(&iter); + RNA_parameter_list_free(parms); + + if (ret) + return ret; + + if (err==-1) + return NULL; + + Py_RETURN_NONE; +} + /*-----------------------BPy_StructRNA method def------------------------------*/ PyTypeObject pyrna_struct_Type = { #if (PY_VERSION_HEX >= 0x02060000) @@ -1089,6 +1511,92 @@ PyTypeObject pyrna_prop_Type = { NULL }; +/*-----------------------BPy_FunctionRNA method def------------------------------*/ +PyTypeObject pyrna_func_Type = { +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif + + "FunctionRNA", /* tp_name */ + sizeof( BPy_FunctionRNA ), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + ( destructor ) pyrna_function_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + ( cmpfunc ) pyrna_func_compare, /* tp_compare */ + ( reprfunc ) pyrna_func_repr, /* tp_repr */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + (ternaryfunc)pyrna_func_call, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /*PyObject_GenericGetAttr - MINGW Complains, assign later */ /* getattrofunc tp_getattro; */ /* will only use these if this is a subtype of a py class */ + NULL, /*PyObject_GenericSetAttr - MINGW Complains, assign later */ /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + (richcmpfunc)pyrna_func_richcmp, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + (getiterfunc)NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + pyrna_func_new, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL +}; + PyObject* pyrna_struct_Subtype(PointerRNA *ptr) { PyObject *newclass = NULL; @@ -1096,12 +1604,12 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr) if (ptr->type==NULL) { newclass= NULL; /* Nothing to do */ - } else if ((newclass= (PyObject *)BPy_RNA_PYTYPE(ptr->data))) { + } else if ((newclass= RNA_struct_py_type_get(ptr->data))) { Py_INCREF(newclass); } else if ((nameprop = RNA_struct_name_property(ptr))) { /* for now, return the base RNA type rather then a real module */ - /* Assume BPy_RNA_PYTYPE(ptr->data) was alredy checked */ + /* Assume RNA_struct_py_type_get(ptr->data) was alredy checked */ /* subclass equivelents - class myClass(myBase): @@ -1140,7 +1648,7 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr) if (newclass) { PyObject *rna; - BPy_RNA_PYTYPE(ptr->data) = (void *)newclass; /* Store for later use */ + RNA_struct_py_type_set(ptr->data, (void *)newclass); /* Store for later use */ /* Not 100% needed but useful, * having an instance within a type looks wrong however this instance IS an rna type */ @@ -1152,9 +1660,8 @@ PyObject* pyrna_struct_Subtype(PointerRNA *ptr) Py_DECREF(args); - if ((char *)&name != nameptr) + if (name != nameptr) MEM_freeN(nameptr); - } return newclass; @@ -1211,6 +1718,25 @@ PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop ) return ( PyObject * ) pyrna; } +PyObject *pyrna_func_CreatePyObject( PointerRNA *ptr, FunctionRNA *func ) +{ + BPy_FunctionRNA *pyrna; + + pyrna = ( BPy_FunctionRNA * ) PyObject_NEW( BPy_FunctionRNA, &pyrna_func_Type ); + + if( !pyrna ) { + PyErr_SetString( PyExc_MemoryError, "couldn't create BPy_FunctionRNA object" ); + return NULL; + } + + pyrna->ptr = *ptr; + pyrna->func = func; + + /* TODO - iterator? */ + + return ( PyObject * ) pyrna; +} + PyObject *BPY_rna_module( void ) { @@ -1226,6 +1752,8 @@ PyObject *BPY_rna_module( void ) if( PyType_Ready( &pyrna_prop_Type ) < 0 ) return NULL; + if( PyType_Ready( &pyrna_func_Type ) < 0 ) + return NULL; /* for now, return the base RNA type rather then a real module */ RNA_main_pointer_create(G.main, &ptr); @@ -1291,7 +1819,7 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self) return list; } -PyTypeObject pyrna_basetype_Type = {NULL}; +PyTypeObject pyrna_basetype_Type = {}; PyObject *BPY_rna_types(void) { diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 878b2a7d17a..059eedb4020 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -32,15 +32,14 @@ extern PyTypeObject pyrna_struct_Type; extern PyTypeObject pyrna_prop_Type; +extern PyTypeObject pyrna_func_Type; #define BPy_StructRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_struct_Type)) #define BPy_StructRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_struct_Type) #define BPy_PropertyRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_prop_Type)) #define BPy_PropertyRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_prop_Type) - - //XXX add propper accessor function, we know this is just after next/prev pointers - - #define BPy_RNA_PYTYPE( _data ) (((BPy_StructFakeType *)(_data))->py_type) +#define BPy_FunctionRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_func_Type)) +#define BPy_FunctionRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_func_Type) typedef struct { void * _a; @@ -61,6 +60,12 @@ typedef struct { PropertyRNA *prop; } BPy_PropertyRNA; +typedef struct { + PyObject_HEAD /* required python macro */ + PointerRNA ptr; + FunctionRNA *func; +} BPy_FunctionRNA; + /* cheap trick */ #define BPy_BaseTypeRNA BPy_PropertyRNA @@ -70,11 +75,14 @@ PyObject *BPY_rna_types( void ); PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr ); PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop ); +PyObject *pyrna_func_CreatePyObject( PointerRNA *ptr, FunctionRNA *func ); /* operators also need this to set args */ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, PyObject *value); PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop); +PyObject *pyrna_func_to_py( PointerRNA *ptr, FunctionRNA *func ); + /* functions for setting up new props - experemental */ PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw); PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw); |