2010-01-09 23:44:01 +00:00
2008-11-29 13:36:08 +00:00
/**
* $ Id $
*
* * * * * * 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 ,
2010-02-12 13:34:04 +00:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2008-11-29 13:36:08 +00:00
*
* Contributor ( s ) : Campbell Barton
*
* * * * * * END GPL LICENSE BLOCK * * * * *
*/
# include "bpy_rna.h"
2010-01-19 00:59:36 +00:00
# include "bpy_props.h"
2009-04-07 00:49:39 +00:00
# include "bpy_util.h"
2008-11-30 14:00:14 +00:00
//#include "blendef.h"
# include "BLI_dynstr.h"
2009-03-19 19:03:38 +00:00
# include "BLI_listbase.h"
2009-04-19 13:37:59 +00:00
# include "BLI_string.h"
2009-03-16 15:54:43 +00:00
# include "float.h" /* FLT_MIN/MAX */
2009-04-19 13:37:59 +00:00
# include "RNA_access.h"
2009-03-16 15:54:43 +00:00
# include "RNA_define.h" /* for defining our own rna */
2010-02-15 23:43:51 +00:00
# include "RNA_enum_types.h"
2008-11-29 13:36:08 +00:00
# include "MEM_guardedalloc.h"
2009-07-01 13:31:36 +00:00
# include "BKE_utildefines.h"
2009-03-19 19:03:38 +00:00
# include "BKE_context.h"
2008-11-29 13:36:08 +00:00
# include "BKE_global.h" /* evil G.* */
2009-04-19 13:37:59 +00:00
# include "BKE_report.h"
2008-11-29 13:36:08 +00:00
2009-11-25 10:13:24 +00:00
# include "BKE_animsys.h"
# include "BKE_fcurve.h"
2009-07-08 09:23:49 +00:00
/* only for keyframing */
# include "DNA_scene_types.h"
2009-11-04 15:16:41 +00:00
# include "DNA_anim_types.h"
2009-07-08 09:23:49 +00:00
# include "ED_keyframing.h"
2009-06-22 04:26:48 +00:00
# define USE_MATHUTILS
# ifdef USE_MATHUTILS
# include "../generic/Mathutils.h" /* so we can have mathutils callbacks */
2009-11-16 19:03:40 +00:00
# include "../generic/IDProp.h" /* for IDprop lookups */
2009-06-22 04:26:48 +00:00
2010-02-15 23:43:51 +00:00
# include <string.h>
2010-02-01 22:04:33 +00:00
2010-02-15 23:43:51 +00:00
static PyObject * pyrna_prop_array_subscript_slice ( BPy_PropertyRNA * self , PointerRNA * ptr , PropertyRNA * prop , int start , int stop , int length ) ;
static Py_ssize_t pyrna_prop_array_length ( BPy_PropertyRNA * self ) ;
static Py_ssize_t pyrna_prop_collection_length ( BPy_PropertyRNA * self ) ;
2010-01-02 17:33:44 +00:00
2010-02-21 14:48:28 +00:00
2009-06-25 10:11:37 +00:00
/* bpyrna vector/euler/quat callbacks */
static int mathutils_rna_array_cb_index = - 1 ; /* index for our callbacks */
2009-06-22 04:26:48 +00:00
2010-02-20 19:49:04 +00:00
/* not used yet but may want to use the subtype below */
# define MATHUTILS_CB_SUBTYPE_EUL 0
# define MATHUTILS_CB_SUBTYPE_VEC 1
# define MATHUTILS_CB_SUBTYPE_QUAT 2
2009-06-23 13:34:45 +00:00
static int mathutils_rna_generic_check ( BPy_PropertyRNA * self )
2009-06-22 04:26:48 +00:00
{
2009-06-23 12:36:15 +00:00
return self - > prop ? 1 : 0 ;
2009-06-22 04:26:48 +00:00
}
static int mathutils_rna_vector_get ( BPy_PropertyRNA * self , int subtype , float * vec_from )
{
if ( self - > prop = = NULL )
return 0 ;
RNA_property_float_get_array ( & self - > ptr , self - > prop , vec_from ) ;
return 1 ;
}
static int mathutils_rna_vector_set ( BPy_PropertyRNA * self , int subtype , float * vec_to )
{
if ( self - > prop = = NULL )
return 0 ;
2010-02-21 14:48:28 +00:00
/* TODO, clamp */
2009-06-22 04:26:48 +00:00
RNA_property_float_set_array ( & self - > ptr , self - > prop , vec_to ) ;
2009-10-30 13:58:43 +00:00
RNA_property_update ( BPy_GetContext ( ) , & self - > ptr , self - > prop ) ;
2009-06-22 04:26:48 +00:00
return 1 ;
}
static int mathutils_rna_vector_get_index ( BPy_PropertyRNA * self , int subtype , float * vec_from , int index )
{
if ( self - > prop = = NULL )
return 0 ;
vec_from [ index ] = RNA_property_float_get_index ( & self - > ptr , self - > prop , index ) ;
return 1 ;
}
static int mathutils_rna_vector_set_index ( BPy_PropertyRNA * self , int subtype , float * vec_to , int index )
{
if ( self - > prop = = NULL )
return 0 ;
2010-02-21 14:48:28 +00:00
RNA_property_float_clamp ( & self - > ptr , self - > prop , & vec_to [ index ] ) ;
2009-06-22 04:26:48 +00:00
RNA_property_float_set_index ( & self - > ptr , self - > prop , index , vec_to [ index ] ) ;
2009-10-30 13:58:43 +00:00
RNA_property_update ( BPy_GetContext ( ) , & self - > ptr , self - > prop ) ;
2009-06-22 04:26:48 +00:00
return 1 ;
}
2009-06-25 10:11:37 +00:00
Mathutils_Callback mathutils_rna_array_cb = {
2009-07-10 18:09:53 +00:00
( BaseMathCheckFunc ) mathutils_rna_generic_check ,
( BaseMathGetFunc ) mathutils_rna_vector_get ,
( BaseMathSetFunc ) mathutils_rna_vector_set ,
( BaseMathGetIndexFunc ) mathutils_rna_vector_get_index ,
( BaseMathSetIndexFunc ) mathutils_rna_vector_set_index
2009-06-22 04:26:48 +00:00
} ;
2009-07-10 18:09:53 +00:00
2009-06-23 13:34:45 +00:00
/* bpyrna matrix callbacks */
static int mathutils_rna_matrix_cb_index = - 1 ; /* index for our callbacks */
static int mathutils_rna_matrix_get ( BPy_PropertyRNA * self , int subtype , float * mat_from )
{
if ( self - > prop = = NULL )
return 0 ;
RNA_property_float_get_array ( & self - > ptr , self - > prop , mat_from ) ;
return 1 ;
}
static int mathutils_rna_matrix_set ( BPy_PropertyRNA * self , int subtype , float * mat_to )
{
if ( self - > prop = = NULL )
return 0 ;
2010-02-21 14:48:28 +00:00
/* can ignore clamping here */
2009-06-23 13:34:45 +00:00
RNA_property_float_set_array ( & self - > ptr , self - > prop , mat_to ) ;
2009-10-30 13:58:43 +00:00
RNA_property_update ( BPy_GetContext ( ) , & self - > ptr , self - > prop ) ;
2009-06-23 13:34:45 +00:00
return 1 ;
}
Mathutils_Callback mathutils_rna_matrix_cb = {
2009-07-10 18:09:53 +00:00
( BaseMathCheckFunc ) mathutils_rna_generic_check ,
( BaseMathGetFunc ) mathutils_rna_matrix_get ,
( BaseMathSetFunc ) mathutils_rna_matrix_set ,
( BaseMathGetIndexFunc ) NULL ,
( BaseMathSetIndexFunc ) NULL
2009-06-23 13:34:45 +00:00
} ;
2010-01-04 13:29:55 +00:00
# define PROP_ALL_VECTOR_SUBTYPES PROP_TRANSLATION: case PROP_DIRECTION: case PROP_VELOCITY: case PROP_ACCELERATION: case PROP_XYZ: case PROP_XYZ|PROP_UNIT_LENGTH
2009-09-06 15:13:57 +00:00
PyObject * pyrna_math_object_from_array ( PointerRNA * ptr , PropertyRNA * prop )
{
PyObject * ret = NULL ;
# ifdef USE_MATHUTILS
2009-11-24 20:15:24 +00:00
int subtype , totdim ;
2009-09-06 15:13:57 +00:00
int len ;
2009-12-28 22:59:09 +00:00
int is_thick ;
2010-01-04 13:29:55 +00:00
int flag = RNA_property_flag ( prop ) ;
2009-09-06 15:13:57 +00:00
2009-11-24 20:15:24 +00:00
/* disallow dynamic sized arrays to be wrapped since the size could change
* to a size mathutils does not support */
2010-01-04 13:29:55 +00:00
if ( ( RNA_property_type ( prop ) ! = PROP_FLOAT ) | | ( flag & PROP_DYNAMIC ) )
2009-11-24 20:15:24 +00:00
return NULL ;
2009-09-06 15:13:57 +00:00
len = RNA_property_array_length ( ptr , prop ) ;
subtype = RNA_property_subtype ( prop ) ;
2009-09-09 19:40:46 +00:00
totdim = RNA_property_array_dimension ( ptr , prop , NULL ) ;
2010-01-04 13:29:55 +00:00
is_thick = ( flag & PROP_THICK_WRAP ) ;
2009-09-06 15:13:57 +00:00
if ( totdim = = 1 | | ( totdim = = 2 & & subtype = = PROP_MATRIX ) ) {
2009-12-28 22:59:09 +00:00
if ( ! is_thick )
ret = pyrna_prop_CreatePyObject ( ptr , prop ) ; /* owned by the Mathutils PyObject */
2009-09-06 15:13:57 +00:00
2009-12-10 10:23:53 +00:00
switch ( RNA_property_subtype ( prop ) ) {
2010-01-04 13:29:55 +00:00
case PROP_ALL_VECTOR_SUBTYPES :
2009-09-06 15:13:57 +00:00
if ( len > = 2 & & len < = 4 ) {
2009-12-28 22:59:09 +00:00
if ( is_thick ) {
ret = newVectorObject ( NULL , len , Py_NEW , NULL ) ;
RNA_property_float_get_array ( ptr , prop , ( ( VectorObject * ) ret ) - > vec ) ;
}
else {
2010-02-20 19:49:04 +00:00
PyObject * vec_cb = newVectorObject_cb ( ret , len , mathutils_rna_array_cb_index , MATHUTILS_CB_SUBTYPE_VEC ) ;
2009-12-28 22:59:09 +00:00
Py_DECREF ( ret ) ; /* the vector owns now */
ret = vec_cb ; /* return the vector instead */
}
2009-09-06 15:13:57 +00:00
}
break ;
case PROP_MATRIX :
if ( len = = 16 ) {
2009-12-28 22:59:09 +00:00
if ( is_thick ) {
ret = newMatrixObject ( NULL , 4 , 4 , Py_NEW , NULL ) ;
RNA_property_float_get_array ( ptr , prop , ( ( MatrixObject * ) ret ) - > contigPtr ) ;
}
else {
PyObject * mat_cb = newMatrixObject_cb ( ret , 4 , 4 , mathutils_rna_matrix_cb_index , FALSE ) ;
Py_DECREF ( ret ) ; /* the matrix owns now */
ret = mat_cb ; /* return the matrix instead */
}
2009-09-06 15:13:57 +00:00
}
else if ( len = = 9 ) {
2009-12-28 22:59:09 +00:00
if ( is_thick ) {
ret = newMatrixObject ( NULL , 3 , 3 , Py_NEW , NULL ) ;
RNA_property_float_get_array ( ptr , prop , ( ( MatrixObject * ) ret ) - > contigPtr ) ;
}
else {
PyObject * mat_cb = newMatrixObject_cb ( ret , 3 , 3 , mathutils_rna_matrix_cb_index , FALSE ) ;
Py_DECREF ( ret ) ; /* the matrix owns now */
ret = mat_cb ; /* return the matrix instead */
}
2009-09-06 15:13:57 +00:00
}
break ;
case PROP_EULER :
case PROP_QUATERNION :
if ( len = = 3 ) { /* euler */
2009-12-28 22:59:09 +00:00
if ( is_thick ) {
2010-02-20 19:49:04 +00:00
ret = newEulerObject ( NULL , 0 , Py_NEW , NULL ) ; // TODO, get order from RNA
2009-12-28 22:59:09 +00:00
RNA_property_float_get_array ( ptr , prop , ( ( EulerObject * ) ret ) - > eul ) ;
}
else {
2010-02-20 19:49:04 +00:00
PyObject * eul_cb = newEulerObject_cb ( ret , 0 , mathutils_rna_array_cb_index , MATHUTILS_CB_SUBTYPE_EUL ) ; // TODO, get order from RNA
2009-12-28 22:59:09 +00:00
Py_DECREF ( ret ) ; /* the matrix owns now */
ret = eul_cb ; /* return the matrix instead */
}
2009-09-06 15:13:57 +00:00
}
else if ( len = = 4 ) {
2009-12-28 22:59:09 +00:00
if ( is_thick ) {
ret = newQuaternionObject ( NULL , Py_NEW , NULL ) ;
RNA_property_float_get_array ( ptr , prop , ( ( QuaternionObject * ) ret ) - > quat ) ;
}
else {
2010-02-20 19:49:04 +00:00
PyObject * quat_cb = newQuaternionObject_cb ( ret , mathutils_rna_array_cb_index , MATHUTILS_CB_SUBTYPE_QUAT ) ;
2009-12-28 22:59:09 +00:00
Py_DECREF ( ret ) ; /* the matrix owns now */
ret = quat_cb ; /* return the matrix instead */
}
2009-09-06 15:13:57 +00:00
}
break ;
default :
break ;
}
}
2009-12-28 22:59:09 +00:00
2010-01-02 17:33:44 +00:00
if ( ret = = NULL ) {
if ( is_thick ) {
/* this is an array we cant reference (since its not thin wrappable)
* and cannot be coerced into a mathutils type , so return as a list */
2010-02-15 23:43:51 +00:00
ret = pyrna_prop_array_subscript_slice ( NULL , ptr , prop , 0 , len , len ) ;
2010-01-02 17:33:44 +00:00
} else {
ret = pyrna_prop_CreatePyObject ( ptr , prop ) ; /* owned by the Mathutils PyObject */
}
}
2009-12-28 22:59:09 +00:00
2009-09-06 15:13:57 +00:00
# endif
return ret ;
}
2009-06-22 04:26:48 +00:00
# endif
2008-11-29 13:36:08 +00:00
static int pyrna_struct_compare ( BPy_StructRNA * a , BPy_StructRNA * b )
2009-01-29 09:38:52 +00:00
{
2008-11-29 13:36:08 +00:00
return ( a - > ptr . data = = b - > ptr . data ) ? 0 : - 1 ;
}
static int pyrna_prop_compare ( BPy_PropertyRNA * a , BPy_PropertyRNA * b )
{
return ( a - > prop = = b - > prop & & a - > ptr . data = = b - > ptr . data ) ? 0 : - 1 ;
}
2009-01-29 09:38:52 +00:00
2009-09-03 01:52:10 +00:00
static PyObject * pyrna_struct_richcmp ( PyObject * a , PyObject * b , int op )
2009-01-29 09:38:52 +00:00
{
2009-09-03 01:52:10 +00:00
PyObject * res ;
int ok = - 1 ; /* zero is true */
if ( BPy_StructRNA_Check ( a ) & & BPy_StructRNA_Check ( b ) )
ok = pyrna_struct_compare ( ( BPy_StructRNA * ) a , ( BPy_StructRNA * ) b ) ;
switch ( op ) {
case Py_NE :
ok = ! ok ; /* pass through */
case Py_EQ :
res = ok ? Py_False : Py_True ;
break ;
case Py_LT :
case Py_LE :
case Py_GT :
case Py_GE :
res = Py_NotImplemented ;
break ;
default :
PyErr_BadArgument ( ) ;
return NULL ;
2009-01-29 09:38:52 +00:00
}
2009-09-03 01:52:10 +00:00
Py_INCREF ( res ) ;
return res ;
2009-01-29 09:38:52 +00:00
}
2009-09-03 01:52:10 +00:00
static PyObject * pyrna_prop_richcmp ( PyObject * a , PyObject * b , int op )
2009-01-29 09:38:52 +00:00
{
2009-09-03 01:52:10 +00:00
PyObject * res ;
int ok = - 1 ; /* zero is true */
if ( BPy_PropertyRNA_Check ( a ) & & BPy_PropertyRNA_Check ( b ) )
ok = pyrna_prop_compare ( ( BPy_PropertyRNA * ) a , ( BPy_PropertyRNA * ) b ) ;
switch ( op ) {
case Py_NE :
ok = ! ok ; /* pass through */
case Py_EQ :
res = ok ? Py_False : Py_True ;
break ;
case Py_LT :
case Py_LE :
case Py_GT :
case Py_GE :
res = Py_NotImplemented ;
break ;
default :
PyErr_BadArgument ( ) ;
return NULL ;
2009-01-29 09:38:52 +00:00
}
2009-09-03 01:52:10 +00:00
Py_INCREF ( res ) ;
return res ;
2009-01-29 09:38:52 +00:00
}
2009-04-07 00:49:39 +00:00
2008-11-29 13:36:08 +00:00
/*----------------------repr--------------------------------------------*/
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_struct_repr ( BPy_StructRNA * self )
2008-11-29 13:36:08 +00:00
{
2009-06-24 14:03:55 +00:00
PyObject * pyob ;
char * name ;
2009-03-23 13:28:42 +00:00
/* print name if available */
2009-07-26 18:18:14 +00:00
name = RNA_struct_name_get_alloc ( & self - > ptr , NULL , FALSE ) ;
2009-06-24 14:03:55 +00:00
if ( name ) {
2010-02-15 23:43:51 +00:00
pyob = PyUnicode_FromFormat ( " <bpy_struct, %.200s( \" %.200s \" )> " , RNA_struct_identifier ( self - > ptr . type ) , name ) ;
2009-06-24 14:03:55 +00:00
MEM_freeN ( name ) ;
return pyob ;
2009-03-23 13:28:42 +00:00
}
2010-02-15 23:43:51 +00:00
return PyUnicode_FromFormat ( " <bpy_struct, %.200s> " , RNA_struct_identifier ( self - > ptr . type ) ) ;
2008-11-29 13:36:08 +00:00
}
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_prop_repr ( BPy_PropertyRNA * self )
2008-11-29 13:36:08 +00:00
{
2009-06-24 14:03:55 +00:00
PyObject * pyob ;
2009-03-23 13:28:42 +00:00
PointerRNA ptr ;
2009-06-24 14:03:55 +00:00
char * name ;
2010-02-15 23:43:51 +00:00
const char * type_id = NULL ;
char type_fmt [ 64 ] = " " ;
int type = RNA_property_type ( self - > prop ) ;
if ( RNA_enum_id_from_value ( property_type_items , type , & type_id ) = = 0 ) {
PyErr_SetString ( PyExc_SystemError , " could not use property type, internal error " ) ; /* should never happen */
return NULL ;
}
else {
/* this should never fail */
int len = - 1 ;
char * c = type_fmt ;
while ( ( * c + + = tolower ( * type_id + + ) ) ) { } ;
if ( type = = PROP_COLLECTION ) {
len = pyrna_prop_collection_length ( self ) ;
} else if ( RNA_property_array_check ( & self - > ptr , self - > prop ) ) {
len = pyrna_prop_array_length ( self ) ;
}
if ( len ! = - 1 )
sprintf ( - - c , " [%d] " , len ) ;
}
2009-03-23 13:28:42 +00:00
/* if a pointer, try to print name of pointer target too */
2009-04-19 13:37:59 +00:00
if ( RNA_property_type ( self - > prop ) = = PROP_POINTER ) {
2009-03-23 13:28:42 +00:00
ptr = RNA_property_pointer_get ( & self - > ptr , self - > prop ) ;
2009-07-26 18:18:14 +00:00
name = RNA_struct_name_get_alloc ( & ptr , NULL , FALSE ) ;
2009-03-23 13:28:42 +00:00
2009-06-24 14:03:55 +00:00
if ( name ) {
2010-02-15 23:43:51 +00:00
pyob = PyUnicode_FromFormat ( " <bpy_%.200s, %.200s.%.200s( \" %.200s \" )> " , type_fmt , RNA_struct_identifier ( self - > ptr . type ) , RNA_property_identifier ( self - > prop ) , name ) ;
2009-06-24 14:03:55 +00:00
MEM_freeN ( name ) ;
return pyob ;
2009-03-23 13:28:42 +00:00
}
}
2010-02-15 23:43:51 +00:00
return PyUnicode_FromFormat ( " <bpy_%.200s, %.200s.%.200s> " , type_fmt , RNA_struct_identifier ( self - > ptr . type ) , RNA_property_identifier ( self - > prop ) ) ;
2008-11-29 13:36:08 +00:00
}
2009-04-09 17:31:23 +00:00
2009-11-16 19:03:40 +00:00
static long pyrna_struct_hash ( BPy_StructRNA * self )
2008-12-02 14:36:35 +00:00
{
return ( long ) self - > ptr . data ;
}
2008-12-29 03:24:13 +00:00
/* use our own dealloc so we can free a property if we use one */
2009-11-16 19:03:40 +00:00
static void pyrna_struct_dealloc ( BPy_StructRNA * self )
2008-12-29 03:24:13 +00:00
{
2009-01-08 15:29:09 +00:00
if ( self - > freeptr & & self - > ptr . data ) {
2010-01-29 14:49:21 +00:00
IDP_FreeProperty ( self - > ptr . data ) ;
MEM_freeN ( self - > ptr . data ) ;
self - > ptr . data = NULL ;
2008-12-29 03:24:13 +00:00
}
2009-06-29 12:06:46 +00:00
/* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */
2009-03-16 15:54:43 +00:00
Py_TYPE ( self ) - > tp_free ( self ) ;
2008-12-29 03:24:13 +00:00
return ;
}
2009-04-07 00:49:39 +00:00
2008-12-25 10:48:36 +00:00
static char * pyrna_enum_as_string ( PointerRNA * ptr , PropertyRNA * prop )
{
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
EnumPropertyItem * item ;
char * result ;
2009-07-26 18:18:14 +00:00
int free = FALSE ;
2008-12-25 10:48:36 +00:00
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
RNA_property_enum_items ( BPy_GetContext ( ) , ptr , prop , & item , NULL , & free ) ;
2009-07-13 19:33:59 +00:00
if ( item ) {
2010-02-10 11:10:38 +00:00
result = BPy_enum_as_string ( item ) ;
2009-07-13 19:33:59 +00:00
}
else {
result = " " ;
}
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
if ( free )
MEM_freeN ( item ) ;
return result ;
2008-12-25 10:48:36 +00:00
}
2008-12-02 14:36:35 +00:00
2010-02-10 11:10:38 +00:00
2009-08-07 13:00:39 +00:00
static int pyrna_string_to_enum ( PyObject * item , PointerRNA * ptr , PropertyRNA * prop , int * val , const char * error_prefix )
{
char * param = _PyUnicode_AsString ( item ) ;
if ( param = = NULL ) {
char * enum_str = pyrna_enum_as_string ( ptr , prop ) ;
PyErr_Format ( PyExc_TypeError , " %.200s expected a string enum type in (%.200s) " , error_prefix , enum_str ) ;
MEM_freeN ( enum_str ) ;
return 0 ;
} else {
if ( ! RNA_property_enum_value ( BPy_GetContext ( ) , ptr , prop , param , val ) ) {
char * enum_str = pyrna_enum_as_string ( ptr , prop ) ;
PyErr_Format ( PyExc_TypeError , " %.200s enum \" %.200s \" not found in (%.200s) " , error_prefix , param , enum_str ) ;
MEM_freeN ( enum_str ) ;
return 0 ;
}
}
return 1 ;
}
2010-02-01 22:04:33 +00:00
int pyrna_set_to_enum_bitfield ( EnumPropertyItem * items , PyObject * value , int * r_value , const char * error_prefix )
{
/* set of enum items, concatenate all values with OR */
int ret , flag = 0 ;
/* set looping */
Py_ssize_t pos = 0 ;
PyObject * key ;
long hash ;
* r_value = 0 ;
while ( _PySet_NextEntry ( value , & pos , & key , & hash ) ) {
char * param = _PyUnicode_AsString ( key ) ;
if ( param = = NULL ) {
PyErr_Format ( PyExc_TypeError , " %s expected a string. found a %.200s " , error_prefix , Py_TYPE ( key ) - > tp_name ) ;
return - 1 ;
}
2010-02-02 23:03:56 +00:00
if ( RNA_enum_value_from_id ( items , param , & ret ) = = 0 ) {
2010-02-01 22:04:33 +00:00
char * enum_str = BPy_enum_as_string ( items ) ;
PyErr_Format ( PyExc_TypeError , " %s \" %.200s \" not found in (%.200s) " , error_prefix , param , enum_str ) ;
MEM_freeN ( enum_str ) ;
return - 1 ;
}
flag | = ret ;
}
* r_value = flag ;
return 0 ;
}
static int pyrna_prop_to_enum_bitfield ( PointerRNA * ptr , PropertyRNA * prop , PyObject * value , int * r_value , const char * error_prefix )
{
EnumPropertyItem * item ;
int ret ;
int free = FALSE ;
* r_value = 0 ;
RNA_property_enum_items ( BPy_GetContext ( ) , ptr , prop , & item , NULL , & free ) ;
if ( item ) {
ret = pyrna_set_to_enum_bitfield ( item , value , r_value , error_prefix ) ;
}
else {
if ( PySet_GET_SIZE ( value ) ) {
PyErr_Format ( PyExc_TypeError , " %s: empty enum \" %.200s \" could not have any values assigned. " , error_prefix , RNA_property_identifier ( prop ) ) ;
ret = - 1 ;
}
else {
ret = 0 ;
}
}
if ( free )
MEM_freeN ( item ) ;
return ret ;
}
2010-01-23 01:02:53 +00:00
PyObject * pyrna_enum_bitfield_to_py ( EnumPropertyItem * items , int value )
{
PyObject * ret = PySet_New ( NULL ) ;
const char * identifier [ RNA_ENUM_BITFLAG_SIZE + 1 ] ;
if ( RNA_enum_bitflag_identifiers ( items , value , identifier ) ) {
PyObject * item ;
int index ;
for ( index = 0 ; identifier [ index ] ; index + + ) {
item = PyUnicode_FromString ( identifier [ index ] ) ;
PySet_Add ( ret , item ) ;
Py_DECREF ( item ) ;
}
}
return ret ;
}
2009-12-07 00:16:57 +00:00
static PyObject * pyrna_enum_to_py ( PointerRNA * ptr , PropertyRNA * prop , int val )
2008-11-29 13:36:08 +00:00
{
2009-12-07 02:20:55 +00:00
PyObject * item , * ret = NULL ;
2009-03-05 08:53:29 +00:00
2009-12-07 00:16:57 +00:00
if ( RNA_property_flag ( prop ) & PROP_ENUM_FLAG ) {
const char * identifier [ RNA_ENUM_BITFLAG_SIZE + 1 ] ;
2009-12-07 02:20:55 +00:00
ret = PySet_New ( NULL ) ;
if ( RNA_property_enum_bitflag_identifiers ( BPy_GetContext ( ) , ptr , prop , val , identifier ) ) {
int index ;
2009-12-07 00:16:57 +00:00
2009-12-07 02:20:55 +00:00
for ( index = 0 ; identifier [ index ] ; index + + ) {
item = PyUnicode_FromString ( identifier [ index ] ) ;
PySet_Add ( ret , item ) ;
Py_DECREF ( item ) ;
2009-12-07 00:16:57 +00:00
}
2009-12-07 02:20:55 +00:00
2009-12-07 00:16:57 +00:00
}
2008-11-29 13:36:08 +00:00
}
2009-12-07 00:16:57 +00:00
else {
2008-12-02 14:36:35 +00:00
const char * identifier ;
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
if ( RNA_property_enum_identifier ( BPy_GetContext ( ) , ptr , prop , val , & identifier ) ) {
2009-12-07 00:16:57 +00:00
ret = PyUnicode_FromString ( identifier ) ;
2008-11-29 17:58:17 +00:00
} else {
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
EnumPropertyItem * item ;
2009-07-26 18:18:14 +00:00
int free = FALSE ;
2009-07-03 19:56:19 +00:00
/* don't throw error here, can't trust blender 100% to give the
* right values , python code should not generate error for that */
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
RNA_property_enum_items ( BPy_GetContext ( ) , ptr , prop , & item , NULL , & free ) ;
2009-07-13 19:33:59 +00:00
if ( item & & item - > identifier ) {
2009-12-07 00:16:57 +00:00
ret = PyUnicode_FromString ( item - > identifier ) ;
2009-07-08 09:23:49 +00:00
}
else {
2009-12-07 00:16:57 +00:00
char * ptr_name = RNA_struct_name_get_alloc ( ptr , NULL , FALSE ) ;
2009-07-08 09:23:49 +00:00
/* prefer not fail silently incase of api errors, maybe disable it later */
2009-11-12 15:46:45 +00:00
printf ( " RNA Warning: Current value \" %d \" matches no enum in '%s', '%s', '%s' \n " , val , RNA_struct_identifier ( ptr - > type ) , ptr_name , RNA_property_identifier ( prop ) ) ;
#if 0 // gives python decoding errors while generating docs :(
char error_str [ 256 ] ;
snprintf ( error_str , sizeof ( error_str ) , " RNA Warning: Current value \" %d \" matches no enum in '%s', '%s', '%s' " , val , RNA_struct_identifier ( ptr - > type ) , ptr_name , RNA_property_identifier ( prop ) ) ;
2009-07-08 09:23:49 +00:00
PyErr_Warn ( PyExc_RuntimeWarning , error_str ) ;
2009-11-12 15:46:45 +00:00
# endif
2009-12-07 00:16:57 +00:00
if ( ptr_name )
MEM_freeN ( ptr_name ) ;
2009-07-08 09:23:49 +00:00
2009-07-03 19:56:19 +00:00
ret = PyUnicode_FromString ( " " ) ;
2009-07-08 09:23:49 +00:00
}
2009-07-03 19:56:19 +00:00
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
if ( free )
MEM_freeN ( item ) ;
2009-07-03 19:56:19 +00:00
/*PyErr_Format(PyExc_AttributeError, "RNA Error: Current value \"%d\" matches no enum", val);
ret = NULL ; */
2008-11-29 13:36:08 +00:00
}
2009-12-07 00:16:57 +00:00
}
return ret ;
}
PyObject * pyrna_prop_to_py ( PointerRNA * ptr , PropertyRNA * prop )
{
PyObject * ret ;
int type = RNA_property_type ( prop ) ;
2008-12-02 14:36:35 +00:00
2009-12-07 00:16:57 +00:00
if ( RNA_property_array_check ( ptr , prop ) ) {
return pyrna_py_from_array ( ptr , prop ) ;
}
/* see if we can coorce into a python type - PropertyType */
switch ( type ) {
case PROP_BOOLEAN :
ret = PyBool_FromLong ( RNA_property_boolean_get ( ptr , prop ) ) ;
break ;
case PROP_INT :
ret = PyLong_FromSsize_t ( ( Py_ssize_t ) RNA_property_int_get ( ptr , prop ) ) ;
break ;
case PROP_FLOAT :
ret = PyFloat_FromDouble ( RNA_property_float_get ( ptr , prop ) ) ;
break ;
case PROP_STRING :
{
char * buf ;
buf = RNA_property_string_get_alloc ( ptr , prop , NULL , - 1 ) ;
ret = PyUnicode_FromString ( buf ) ;
MEM_freeN ( buf ) ;
break ;
}
case PROP_ENUM :
{
ret = pyrna_enum_to_py ( ptr , prop , RNA_property_enum_get ( ptr , prop ) ) ;
2008-11-29 13:36:08 +00:00
break ;
}
case PROP_POINTER :
{
PointerRNA newptr ;
2009-02-02 19:57:57 +00:00
newptr = RNA_property_pointer_get ( ptr , prop ) ;
2009-10-09 01:34:46 +00:00
if ( newptr . data ) {
2008-11-29 13:36:08 +00:00
ret = pyrna_struct_CreatePyObject ( & newptr ) ;
} else {
ret = Py_None ;
Py_INCREF ( ret ) ;
}
break ;
}
case PROP_COLLECTION :
2009-03-05 12:09:30 +00:00
ret = pyrna_prop_CreatePyObject ( ptr , prop ) ;
2008-11-29 13:36:08 +00:00
break ;
default :
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_TypeError , " RNA Error: unknown type \" %d \" (pyrna_prop_to_py) " , type ) ;
2008-11-29 13:36:08 +00:00
ret = NULL ;
break ;
}
return ret ;
}
2009-07-30 01:52:00 +00:00
/* This function is used by operators and converting dicts into collections.
* Its takes keyword args and fills them with property values */
int pyrna_pydict_to_props ( PointerRNA * ptr , PyObject * kw , int all_args , const char * error_prefix )
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
{
int error_val = 0 ;
int totkw ;
const char * arg_name = NULL ;
PyObject * item ;
totkw = kw ? PyDict_Size ( kw ) : 0 ;
2009-06-24 21:27:10 +00:00
RNA_STRUCT_BEGIN ( ptr , prop ) {
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
arg_name = RNA_property_identifier ( prop ) ;
if ( strcmp ( arg_name , " rna_type " ) = = 0 ) continue ;
if ( kw = = NULL ) {
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s: no keywords, expected \" %.200s \" " , error_prefix , arg_name ? arg_name : " <UNKNOWN> " ) ;
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
error_val = - 1 ;
break ;
}
2009-07-30 01:52:00 +00:00
item = PyDict_GetItemString ( kw , arg_name ) ; /* wont set an error */
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
if ( item = = NULL ) {
2009-07-30 01:52:00 +00:00
if ( all_args ) {
PyErr_Format ( PyExc_TypeError , " %.200s: keyword \" %.200s \" missing " , error_prefix , arg_name ? arg_name : " <UNKNOWN> " ) ;
error_val = - 1 ; /* pyrna_py_to_prop sets the error */
break ;
}
} else {
2010-01-24 10:51:59 +00:00
if ( pyrna_py_to_prop ( ptr , prop , NULL , NULL , item , error_prefix ) ) {
2009-07-30 01:52:00 +00:00
error_val = - 1 ;
break ;
}
totkw - - ;
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
}
}
2009-06-24 21:27:10 +00:00
RNA_STRUCT_END ;
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
if ( error_val = = 0 & & totkw > 0 ) { /* some keywords were given that were not used :/ */
PyObject * key , * value ;
Py_ssize_t pos = 0 ;
while ( PyDict_Next ( kw , & pos , & key , & value ) ) {
arg_name = _PyUnicode_AsString ( key ) ;
if ( RNA_struct_find_property ( ptr , arg_name ) = = NULL ) break ;
arg_name = NULL ;
}
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s: keyword \" %.200s \" unrecognized " , error_prefix , arg_name ? arg_name : " <UNKNOWN> " ) ;
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
error_val = - 1 ;
}
return error_val ;
}
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_func_call ( PyObject * self , PyObject * args , PyObject * kw ) ;
2009-04-09 13:20:48 +00:00
2009-12-07 02:20:55 +00:00
static PyObject * pyrna_func_to_py ( BPy_DummyPointerRNA * pyrna , FunctionRNA * func )
2009-04-09 17:31:23 +00:00
{
2009-04-09 13:20:48 +00:00
static PyMethodDef func_meth = { " <generic rna function> " , ( PyCFunction ) pyrna_func_call , METH_VARARGS | METH_KEYWORDS , " python rna function " } ;
2009-07-17 12:26:40 +00:00
PyObject * self ;
2009-04-09 13:20:48 +00:00
PyObject * ret ;
2009-07-17 12:26:40 +00:00
if ( func = = NULL ) {
PyErr_Format ( PyExc_RuntimeError , " %.200s: type attempted to get NULL function " , RNA_struct_identifier ( pyrna - > ptr . type ) ) ;
return NULL ;
}
2009-06-25 10:11:37 +00:00
2009-07-17 12:26:40 +00:00
self = PyTuple_New ( 2 ) ;
2009-06-25 10:11:37 +00:00
PyTuple_SET_ITEM ( self , 0 , ( PyObject * ) pyrna ) ;
Py_INCREF ( pyrna ) ;
2010-02-12 21:14:01 +00:00
PyTuple_SET_ITEM ( self , 1 , PyCapsule_New ( ( void * ) func , NULL , NULL ) ) ;
2009-04-09 13:20:48 +00:00
ret = PyCFunction_New ( & func_meth , self ) ;
Py_DECREF ( self ) ;
return ret ;
2009-04-07 00:49:39 +00:00
}
2008-11-29 17:58:17 +00:00
2009-04-16 13:21:18 +00:00
2009-12-07 02:20:55 +00:00
2010-01-24 10:51:59 +00:00
int pyrna_py_to_prop ( PointerRNA * ptr , PropertyRNA * prop , ParameterList * parms , void * data , PyObject * value , const char * error_prefix )
2008-11-29 17:58:17 +00:00
{
2009-04-16 13:21:18 +00:00
/* XXX hard limits should be checked here */
2009-04-19 13:37:59 +00:00
int type = RNA_property_type ( prop ) ;
2008-11-29 17:58:17 +00:00
2009-09-15 10:01:20 +00:00
if ( RNA_property_array_check ( ptr , prop ) ) {
2009-09-06 15:13:57 +00:00
/* char error_str[512]; */
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]
2009-08-25 17:06:36 +00:00
int ok = 1 ;
2009-06-23 17:10:46 +00:00
# ifdef USE_MATHUTILS
if ( MatrixObject_Check ( value ) ) {
MatrixObject * mat = ( MatrixObject * ) value ;
2009-06-25 10:11:37 +00:00
if ( ! BaseMath_ReadCallback ( mat ) )
2009-06-23 17:10:46 +00:00
return - 1 ;
2009-06-25 10:11:37 +00:00
} else /* continue... */
2009-06-23 17:10:46 +00:00
# endif
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]
2009-08-25 17:06:36 +00:00
if ( ! PySequence_Check ( value ) ) {
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s RNA array assignment expected a sequence instead of %.200s instance. " , error_prefix , Py_TYPE ( value ) - > tp_name ) ;
2008-11-30 03:52:07 +00:00
return - 1 ;
2008-11-29 17:58:17 +00:00
}
2009-06-23 17:10:46 +00:00
/* done getting the length */
2010-01-24 10:51:59 +00:00
ok = pyrna_py_to_array ( ptr , prop , parms , data , value , error_prefix ) ;
2009-09-06 15:13:57 +00:00
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]
2009-08-25 17:06:36 +00:00
if ( ! ok ) {
2009-09-06 15:13:57 +00:00
/* PyErr_Format(PyExc_AttributeError, "%.200s %s", error_prefix, error_str); */
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]
2009-08-25 17:06:36 +00:00
return - 1 ;
2008-11-30 03:52:07 +00:00
}
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]
2009-08-25 17:06:36 +00:00
}
else {
2008-11-30 03:52:07 +00:00
/* Normal Property (not an array) */
2008-11-29 17:58:17 +00:00
2008-11-30 03:52:07 +00:00
/* see if we can coorce into a python type - PropertyType */
switch ( type ) {
case PROP_BOOLEAN :
{
2009-11-22 21:51:12 +00:00
int param ;
/* 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 , */
2010-01-24 10:51:59 +00:00
if ( RNA_property_flag ( prop ) & PROP_OUTPUT )
2009-11-22 21:51:12 +00:00
param = PyObject_IsTrue ( value ) ;
else
param = PyLong_AsSsize_t ( value ) ;
2008-11-29 17:58:17 +00:00
2009-11-22 21:51:12 +00:00
if ( param < 0 | | param > 1 ) {
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected True/False or 0/1 " , error_prefix ) ;
2008-11-30 03:52:07 +00:00
return - 1 ;
} else {
2009-04-16 13:21:18 +00:00
if ( data ) * ( ( int * ) data ) = param ;
else RNA_property_boolean_set ( ptr , prop , param ) ;
2008-11-30 03:52:07 +00:00
}
break ;
}
case PROP_INT :
{
int param = PyLong_AsSsize_t ( value ) ;
2009-11-11 16:28:53 +00:00
if ( param = = - 1 & & PyErr_Occurred ( ) ) {
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected an int type " , error_prefix ) ;
2008-11-30 03:52:07 +00:00
return - 1 ;
} else {
2010-02-21 14:48:28 +00:00
RNA_property_int_clamp ( ptr , prop , & param ) ;
2009-04-16 13:21:18 +00:00
if ( data ) * ( ( int * ) data ) = param ;
else RNA_property_int_set ( ptr , prop , param ) ;
2008-11-30 03:52:07 +00:00
}
break ;
}
case PROP_FLOAT :
{
float param = PyFloat_AsDouble ( value ) ;
if ( PyErr_Occurred ( ) ) {
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected a float type " , error_prefix ) ;
2008-11-30 03:52:07 +00:00
return - 1 ;
} else {
2010-02-21 14:48:28 +00:00
RNA_property_float_clamp ( ptr , prop , ( float * ) & param ) ;
2009-04-16 13:21:18 +00:00
if ( data ) * ( ( float * ) data ) = param ;
else RNA_property_float_set ( ptr , prop , param ) ;
2008-11-30 03:52:07 +00:00
}
break ;
}
case PROP_STRING :
{
char * param = _PyUnicode_AsString ( value ) ;
2008-11-29 17:58:17 +00:00
2008-11-30 03:52:07 +00:00
if ( param = = NULL ) {
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected a string type " , error_prefix ) ;
2008-11-30 03:52:07 +00:00
return - 1 ;
} else {
2009-04-16 13:21:18 +00:00
if ( data ) * ( ( char * * ) data ) = param ;
else RNA_property_string_set ( ptr , prop , param ) ;
2008-11-29 17:58:17 +00:00
}
2008-11-30 03:52:07 +00:00
break ;
}
case PROP_ENUM :
{
2010-02-01 22:04:33 +00:00
int val = 0 ;
2009-08-07 13:00:39 +00:00
if ( PyUnicode_Check ( value ) ) {
if ( ! pyrna_string_to_enum ( value , ptr , prop , & val , error_prefix ) )
return - 1 ;
}
2009-12-07 02:20:55 +00:00
else if ( PyAnySet_Check ( value ) ) {
if ( RNA_property_flag ( prop ) & PROP_ENUM_FLAG ) {
/* set of enum items, concatenate all values with OR */
2010-02-01 22:04:33 +00:00
if ( pyrna_prop_to_enum_bitfield ( ptr , prop , value , & val , error_prefix ) < 0 )
return - 1 ;
2009-12-07 02:20:55 +00:00
}
else {
PyErr_Format ( PyExc_TypeError , " %.200s, %.200s.%.200s is not a bitflag enum type " , error_prefix , RNA_struct_identifier ( ptr - > type ) , RNA_property_identifier ( prop ) ) ;
return - 1 ;
2009-08-07 13:00:39 +00:00
}
}
else {
2008-12-25 10:48:36 +00:00
char * enum_str = pyrna_enum_as_string ( ptr , prop ) ;
2009-12-07 02:20:55 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected a string enum or a set of strings in (%.200s) " , error_prefix , enum_str ) ;
2008-12-25 10:48:36 +00:00
MEM_freeN ( enum_str ) ;
2008-11-30 03:52:07 +00:00
return - 1 ;
2008-11-29 17:58:17 +00:00
}
2009-08-07 13:00:39 +00:00
if ( data ) * ( ( int * ) data ) = val ;
else RNA_property_enum_set ( ptr , prop , val ) ;
2008-11-30 03:52:07 +00:00
break ;
}
case PROP_POINTER :
{
2009-06-07 13:09:18 +00:00
StructRNA * ptype = RNA_property_pointer_type ( ptr , prop ) ;
2009-09-16 18:04:01 +00:00
int flag = RNA_property_flag ( prop ) ;
2009-03-23 13:28:42 +00:00
2010-01-26 20:43:27 +00:00
/* if property is an OperatorProperties pointer and value is a map, forward back to pyrna_pydict_to_props */
if ( RNA_struct_is_a ( ptype , & RNA_OperatorProperties ) & & PyDict_Check ( value ) ) {
PointerRNA opptr = RNA_property_pointer_get ( ptr , prop ) ;
return pyrna_pydict_to_props ( & opptr , value , 0 , error_prefix ) ;
}
2009-06-07 13:09:18 +00:00
if ( ! BPy_StructRNA_Check ( value ) & & value ! = Py_None ) {
2009-09-16 18:04:01 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected a %.200s type " , error_prefix , RNA_struct_identifier ( ptype ) ) ;
return - 1 ;
} else if ( ( flag & PROP_NEVER_NULL ) & & value = = Py_None ) {
2010-01-26 17:37:44 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s does not support a 'None' assignment %.200s type " , error_prefix , RNA_struct_identifier ( ptype ) ) ;
2009-03-23 13:28:42 +00:00
return - 1 ;
2010-02-22 08:27:45 +00:00
} else if ( value ! = Py_None & & ( ( flag & PROP_ID_SELF_CHECK ) & & ptr - > id . data = = ( ( BPy_StructRNA * ) value ) - > ptr . id . data ) ) {
PyErr_Format ( PyExc_TypeError , " %.200s ID type does not support assignment to its self " , error_prefix ) ;
return - 1 ;
2009-03-23 13:28:42 +00:00
} else {
BPy_StructRNA * param = ( BPy_StructRNA * ) value ;
2009-07-26 18:18:14 +00:00
int raise_error = FALSE ;
2009-04-16 13:21:18 +00:00
if ( data ) {
2009-06-16 00:52:21 +00:00
if ( flag & PROP_RNAPTR ) {
2009-06-07 13:09:18 +00:00
if ( value = = Py_None )
memset ( data , 0 , sizeof ( PointerRNA ) ) ;
else
* ( ( PointerRNA * ) data ) = param - > ptr ;
}
else if ( value = = Py_None ) {
* ( ( void * * ) data ) = NULL ;
2009-04-16 13:21:18 +00:00
}
2009-04-19 13:37:59 +00:00
else if ( RNA_struct_is_a ( param - > ptr . type , ptype ) ) {
2009-04-16 13:21:18 +00:00
* ( ( void * * ) data ) = param - > ptr . data ;
2009-06-07 13:09:18 +00:00
}
else {
2009-07-26 18:18:14 +00:00
raise_error = TRUE ;
2009-04-16 13:21:18 +00:00
}
}
else {
/* data==NULL, assign to RNA */
2009-06-07 13:09:18 +00:00
if ( value = = Py_None ) {
PointerRNA valueptr ;
memset ( & valueptr , 0 , sizeof ( valueptr ) ) ;
RNA_property_pointer_set ( ptr , prop , valueptr ) ;
}
else if ( RNA_struct_is_a ( param - > ptr . type , ptype ) ) {
2009-04-16 13:21:18 +00:00
RNA_property_pointer_set ( ptr , prop , param - > ptr ) ;
2009-06-07 13:09:18 +00:00
}
else {
2009-04-16 13:21:18 +00:00
PointerRNA tmp ;
RNA_pointer_create ( NULL , ptype , NULL , & tmp ) ;
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected a %.200s type " , error_prefix , RNA_struct_identifier ( tmp . type ) ) ;
2009-04-16 13:21:18 +00:00
return - 1 ;
}
}
if ( raise_error ) {
2009-03-23 13:28:42 +00:00
PointerRNA tmp ;
RNA_pointer_create ( NULL , ptype , NULL , & tmp ) ;
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected a %.200s type " , error_prefix , RNA_struct_identifier ( tmp . type ) ) ;
2009-03-23 13:28:42 +00:00
return - 1 ;
}
}
2008-11-30 03:52:07 +00:00
break ;
}
case PROP_COLLECTION :
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
{
int seq_len , i ;
PyObject * item ;
PointerRNA itemptr ;
2009-06-27 01:10:39 +00:00
ListBase * lb ;
CollectionPointerLink * link ;
lb = ( data ) ? ( ListBase * ) data : NULL ;
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
/* convert a sequence of dict's into a collection */
if ( ! PySequence_Check ( value ) ) {
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected a sequence of dicts for an RNA collection " , error_prefix ) ;
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
return - 1 ;
}
seq_len = PySequence_Length ( value ) ;
for ( i = 0 ; i < seq_len ; i + + ) {
item = PySequence_GetItem ( value , i ) ;
if ( item = = NULL | | PyDict_Check ( item ) = = 0 ) {
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s expected a sequence of dicts for an RNA collection " , error_prefix ) ;
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
Py_XDECREF ( item ) ;
return - 1 ;
}
2009-06-27 01:10:39 +00:00
if ( lb ) {
link = MEM_callocN ( sizeof ( CollectionPointerLink ) , " PyCollectionPointerLink " ) ;
link - > ptr = itemptr ;
BLI_addtail ( lb , link ) ;
}
else
RNA_property_collection_add ( ptr , prop , & itemptr ) ;
2009-07-30 01:52:00 +00:00
if ( pyrna_pydict_to_props ( & itemptr , item , 1 , " Converting a python list to an RNA collection " ) = = - 1 ) {
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
Py_DECREF ( item ) ;
return - 1 ;
}
Py_DECREF ( item ) ;
}
2008-11-30 03:52:07 +00:00
break ;
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
2009-06-05 12:48:58 +00:00
}
2008-11-30 03:52:07 +00:00
default :
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_AttributeError , " %.200s unknown property type (pyrna_py_to_prop) " , error_prefix ) ;
2008-11-30 03:52:07 +00:00
return - 1 ;
break ;
2008-11-29 17:58:17 +00:00
}
}
2009-10-08 07:54:20 +00:00
/* Run rna property functions */
RNA_property_update ( BPy_GetContext ( ) , ptr , prop ) ;
2008-11-30 03:52:07 +00:00
return 0 ;
2008-11-29 17:58:17 +00:00
}
2009-09-06 15:13:57 +00:00
static PyObject * pyrna_prop_to_py_index ( BPy_PropertyRNA * self , int index )
2008-11-29 13:36:08 +00:00
{
2010-01-20 14:06:38 +00:00
return pyrna_py_from_array_index ( self , & self - > ptr , self - > prop , index ) ;
2008-11-29 13:36:08 +00:00
}
2009-09-06 15:13:57 +00:00
static int pyrna_py_to_prop_index ( BPy_PropertyRNA * self , int index , PyObject * value )
2008-11-29 17:58:17 +00:00
{
int ret = 0 ;
2009-09-06 15:13:57 +00:00
int totdim ;
PointerRNA * ptr = & self - > ptr ;
PropertyRNA * prop = self - > prop ;
2009-04-19 13:37:59 +00:00
int type = RNA_property_type ( prop ) ;
2009-09-06 15:13:57 +00:00
2009-09-09 19:40:46 +00:00
totdim = RNA_property_array_dimension ( ptr , prop , NULL ) ;
2009-09-06 15:13:57 +00:00
if ( totdim > 1 ) {
/* char error_str[512]; */
if ( ! pyrna_py_to_array_index ( & self - > ptr , self - > prop , self - > arraydim , self - > arrayoffset , index , value , " " ) ) {
/* PyErr_SetString(PyExc_AttributeError, error_str); */
ret = - 1 ;
2008-11-29 17:58:17 +00:00
}
}
2009-09-06 15:13:57 +00:00
else {
/* see if we can coorce into a python type - PropertyType */
switch ( type ) {
case PROP_BOOLEAN :
{
2009-11-22 21:51:12 +00:00
int param = PyLong_AsSsize_t ( value ) ;
2009-09-06 15:13:57 +00:00
2009-11-22 21:51:12 +00:00
if ( param < 0 | | param > 1 ) {
2009-09-06 15:13:57 +00:00
PyErr_SetString ( PyExc_TypeError , " expected True/False or 0/1 " ) ;
ret = - 1 ;
} else {
RNA_property_boolean_set_index ( ptr , prop , index , param ) ;
}
break ;
}
case PROP_INT :
{
int param = PyLong_AsSsize_t ( value ) ;
2009-11-11 16:28:53 +00:00
if ( param = = - 1 & & PyErr_Occurred ( ) ) {
2009-09-06 15:13:57 +00:00
PyErr_SetString ( PyExc_TypeError , " expected an int type " ) ;
ret = - 1 ;
} else {
2010-02-21 14:48:28 +00:00
RNA_property_int_clamp ( ptr , prop , & param ) ;
2009-09-06 15:13:57 +00:00
RNA_property_int_set_index ( ptr , prop , index , param ) ;
}
break ;
}
case PROP_FLOAT :
{
float param = PyFloat_AsDouble ( value ) ;
if ( PyErr_Occurred ( ) ) {
PyErr_SetString ( PyExc_TypeError , " expected a float type " ) ;
ret = - 1 ;
} else {
2010-02-21 14:48:28 +00:00
RNA_property_float_clamp ( ptr , prop , & param ) ;
2009-09-06 15:13:57 +00:00
RNA_property_float_set_index ( ptr , prop , index , param ) ;
}
break ;
}
default :
PyErr_SetString ( PyExc_AttributeError , " not an array type " ) ;
2008-11-29 17:58:17 +00:00
ret = - 1 ;
2009-09-06 15:13:57 +00:00
break ;
2008-11-29 17:58:17 +00:00
}
}
return ret ;
}
2008-11-29 13:36:08 +00:00
//---------------sequence-------------------------------------------
2010-02-15 23:43:51 +00:00
static Py_ssize_t pyrna_prop_array_length ( BPy_PropertyRNA * self )
2009-09-06 15:13:57 +00:00
{
2009-09-09 19:40:46 +00:00
if ( RNA_property_array_dimension ( & self - > ptr , self - > prop , NULL ) > 1 )
return RNA_property_multi_array_length ( & self - > ptr , self - > prop , self - > arraydim ) ;
2009-09-06 15:13:57 +00:00
else
return RNA_property_array_length ( & self - > ptr , self - > prop ) ;
}
2010-02-15 23:43:51 +00:00
static Py_ssize_t pyrna_prop_collection_length ( BPy_PropertyRNA * self )
2008-11-29 13:36:08 +00:00
{
2010-02-15 23:43:51 +00:00
return RNA_property_collection_length ( & self - > ptr , self - > prop ) ;
2008-11-29 13:36:08 +00:00
}
2009-07-01 13:31:36 +00:00
/* internal use only */
2010-02-15 23:43:51 +00:00
static PyObject * pyrna_prop_collection_subscript_int ( BPy_PropertyRNA * self , Py_ssize_t keynum )
2008-11-29 13:36:08 +00:00
{
PointerRNA newptr ;
2009-07-01 13:31:36 +00:00
if ( keynum < 0 ) keynum + = RNA_property_collection_length ( & self - > ptr , self - > prop ) ;
if ( RNA_property_collection_lookup_int ( & self - > ptr , self - > prop , keynum , & newptr ) )
return pyrna_struct_CreatePyObject ( & newptr ) ;
2009-07-09 08:06:26 +00:00
PyErr_Format ( PyExc_IndexError , " index %d out of range " , keynum ) ;
2009-07-01 13:31:36 +00:00
return NULL ;
}
2009-09-06 15:13:57 +00:00
2010-02-15 23:43:51 +00:00
static PyObject * pyrna_prop_array_subscript_int ( BPy_PropertyRNA * self , int keynum )
2009-07-01 13:31:36 +00:00
{
2009-09-06 15:13:57 +00:00
int len = pyrna_prop_array_length ( self ) ;
2009-07-01 13:31:36 +00:00
if ( keynum < 0 ) keynum + = len ;
if ( keynum > = 0 & & keynum < len )
2009-09-06 15:13:57 +00:00
return pyrna_prop_to_py_index ( self , keynum ) ;
2009-07-01 13:31:36 +00:00
2009-07-09 08:06:26 +00:00
PyErr_Format ( PyExc_IndexError , " index %d out of range " , keynum ) ;
2009-07-01 13:31:36 +00:00
return NULL ;
}
2010-02-15 23:43:51 +00:00
static PyObject * pyrna_prop_collection_subscript_str ( BPy_PropertyRNA * self , char * keyname )
2009-07-01 13:31:36 +00:00
{
PointerRNA newptr ;
if ( RNA_property_collection_lookup_string ( & self - > ptr , self - > prop , keyname , & newptr ) )
return pyrna_struct_CreatePyObject ( & newptr ) ;
2009-07-09 08:06:26 +00:00
PyErr_Format ( PyExc_KeyError , " key \" %.200s \" not found " , keyname ) ;
2009-07-01 13:31:36 +00:00
return NULL ;
}
2010-02-15 23:43:51 +00:00
/* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */
2009-07-01 13:31:36 +00:00
2010-02-15 23:43:51 +00:00
static PyObject * pyrna_prop_collection_subscript_slice ( PointerRNA * ptr , PropertyRNA * prop , int start , int stop , int length )
2009-07-01 13:31:36 +00:00
{
PointerRNA newptr ;
PyObject * list = PyList_New ( stop - start ) ;
int count ;
start = MIN2 ( start , stop ) ; /* values are clamped from */
for ( count = start ; count < stop ; count + + ) {
2010-01-02 17:33:44 +00:00
if ( RNA_property_collection_lookup_int ( ptr , prop , count - start , & newptr ) ) {
PyList_SET_ITEM ( list , count - start , pyrna_struct_CreatePyObject ( & newptr ) ) ;
2009-07-01 13:31:36 +00:00
}
else {
Py_DECREF ( list ) ;
PyErr_SetString ( PyExc_RuntimeError , " error getting an rna struct from a collection " ) ;
return NULL ;
}
}
return list ;
}
2010-01-02 17:33:44 +00:00
/* TODO - dimensions
* note : could also use pyrna_prop_to_py_index ( self , count ) in a loop but its a lot slower
* since at the moment it reads ( and even allocates ) the entire array for each index .
*/
2010-02-15 23:43:51 +00:00
static PyObject * pyrna_prop_array_subscript_slice ( BPy_PropertyRNA * self , PointerRNA * ptr , PropertyRNA * prop , int start , int stop , int length )
2009-07-01 13:31:36 +00:00
{
2010-01-20 14:06:38 +00:00
int count , totdim ;
2009-07-01 13:31:36 +00:00
PyObject * list = PyList_New ( stop - start ) ;
2010-01-20 14:06:38 +00:00
totdim = RNA_property_array_dimension ( ptr , prop , NULL ) ;
if ( totdim > 1 ) {
for ( count = start ; count < stop ; count + + )
PyList_SET_ITEM ( list , count - start , pyrna_prop_to_py_index ( self , count ) ) ;
}
else {
switch ( RNA_property_type ( prop ) ) {
2010-01-02 17:33:44 +00:00
case PROP_FLOAT :
2010-01-20 14:06:38 +00:00
{
float values_stack [ PYRNA_STACK_ARRAY ] ;
float * values ;
if ( length > PYRNA_STACK_ARRAY ) { values = PyMem_MALLOC ( sizeof ( float ) * length ) ; }
else { values = values_stack ; }
RNA_property_float_get_array ( ptr , prop , values ) ;
2010-01-02 17:33:44 +00:00
2010-01-20 14:06:38 +00:00
for ( count = start ; count < stop ; count + + )
PyList_SET_ITEM ( list , count - start , PyFloat_FromDouble ( values [ count ] ) ) ;
2010-01-02 17:33:44 +00:00
2010-01-20 14:06:38 +00:00
if ( values ! = values_stack ) {
PyMem_FREE ( values ) ;
}
break ;
2010-01-02 17:33:44 +00:00
}
case PROP_BOOLEAN :
2010-01-20 14:06:38 +00:00
{
int values_stack [ PYRNA_STACK_ARRAY ] ;
int * values ;
if ( length > PYRNA_STACK_ARRAY ) { values = PyMem_MALLOC ( sizeof ( int ) * length ) ; }
else { values = values_stack ; }
2010-01-02 17:33:44 +00:00
2010-01-20 14:06:38 +00:00
RNA_property_boolean_get_array ( ptr , prop , values ) ;
for ( count = start ; count < stop ; count + + )
PyList_SET_ITEM ( list , count - start , PyBool_FromLong ( values [ count ] ) ) ;
2010-01-02 17:33:44 +00:00
2010-01-20 14:06:38 +00:00
if ( values ! = values_stack ) {
PyMem_FREE ( values ) ;
}
break ;
2010-01-02 17:33:44 +00:00
}
case PROP_INT :
2010-01-20 14:06:38 +00:00
{
int values_stack [ PYRNA_STACK_ARRAY ] ;
int * values ;
if ( length > PYRNA_STACK_ARRAY ) { values = PyMem_MALLOC ( sizeof ( int ) * length ) ; }
else { values = values_stack ; }
2009-07-01 13:31:36 +00:00
2010-01-20 14:06:38 +00:00
RNA_property_int_get_array ( ptr , prop , values ) ;
for ( count = start ; count < stop ; count + + )
PyList_SET_ITEM ( list , count - start , PyLong_FromSsize_t ( values [ count ] ) ) ;
2009-07-01 13:31:36 +00:00
2010-01-20 14:06:38 +00:00
if ( values ! = values_stack ) {
PyMem_FREE ( values ) ;
}
break ;
2010-01-02 17:33:44 +00:00
}
default :
/* probably will never happen */
PyErr_SetString ( PyExc_TypeError , " not an array type " ) ;
Py_DECREF ( list ) ;
list = NULL ;
2010-01-20 14:06:38 +00:00
}
2010-01-02 17:33:44 +00:00
}
2009-07-01 13:31:36 +00:00
return list ;
}
2010-02-15 23:43:51 +00:00
static PyObject * pyrna_prop_collection_subscript ( BPy_PropertyRNA * self , PyObject * key )
2009-07-01 13:31:36 +00:00
{
2008-11-29 13:36:08 +00:00
if ( PyUnicode_Check ( key ) ) {
2010-02-15 23:43:51 +00:00
return pyrna_prop_collection_subscript_str ( self , _PyUnicode_AsString ( key ) ) ;
2009-07-01 13:31:36 +00:00
}
2009-07-08 09:23:49 +00:00
else if ( PyIndex_Check ( key ) ) {
Py_ssize_t i = PyNumber_AsSsize_t ( key , PyExc_IndexError ) ;
if ( i = = - 1 & & PyErr_Occurred ( ) )
return NULL ;
2010-02-15 23:43:51 +00:00
return pyrna_prop_collection_subscript_int ( self , i ) ;
2009-07-01 13:31:36 +00:00
}
else if ( PySlice_Check ( key ) ) {
int len = RNA_property_collection_length ( & self - > ptr , self - > prop ) ;
Py_ssize_t start , stop , step , slicelength ;
if ( PySlice_GetIndicesEx ( ( PySliceObject * ) key , len , & start , & stop , & step , & slicelength ) < 0 )
return NULL ;
if ( slicelength < = 0 ) {
return PyList_New ( 0 ) ;
}
else if ( step = = 1 ) {
2010-02-15 23:43:51 +00:00
return pyrna_prop_collection_subscript_slice ( & self - > ptr , self - > prop , start , stop , len ) ;
2009-07-01 13:31:36 +00:00
}
else {
PyErr_SetString ( PyExc_TypeError , " slice steps not supported with rna " ) ;
return NULL ;
}
}
else {
2009-07-09 08:06:26 +00:00
PyErr_Format ( PyExc_TypeError , " invalid rna key, key must be a string or an int instead of %.200s instance. " , Py_TYPE ( key ) - > tp_name ) ;
2008-11-29 13:36:08 +00:00
return NULL ;
}
2009-07-01 13:31:36 +00:00
}
2010-02-15 23:43:51 +00:00
static PyObject * pyrna_prop_array_subscript ( BPy_PropertyRNA * self , PyObject * key )
2009-07-01 13:31:36 +00:00
{
/*if (PyUnicode_Check(key)) {
2010-02-15 23:43:51 +00:00
return pyrna_prop_array_subscript_str ( self , _PyUnicode_AsString ( key ) ) ;
2009-07-01 13:31:36 +00:00
} else */
2009-07-08 09:23:49 +00:00
if ( PyIndex_Check ( key ) ) {
Py_ssize_t i = PyNumber_AsSsize_t ( key , PyExc_IndexError ) ;
if ( i = = - 1 & & PyErr_Occurred ( ) )
return NULL ;
2010-02-15 23:43:51 +00:00
return pyrna_prop_array_subscript_int ( self , PyLong_AsSsize_t ( key ) ) ;
2009-07-01 13:31:36 +00:00
}
else if ( PySlice_Check ( key ) ) {
Py_ssize_t start , stop , step , slicelength ;
2009-09-06 15:13:57 +00:00
int len = pyrna_prop_array_length ( self ) ;
2009-07-01 13:31:36 +00:00
if ( PySlice_GetIndicesEx ( ( PySliceObject * ) key , len , & start , & stop , & step , & slicelength ) < 0 )
return NULL ;
if ( slicelength < = 0 ) {
return PyList_New ( 0 ) ;
2008-11-29 13:36:08 +00:00
}
2009-07-01 13:31:36 +00:00
else if ( step = = 1 ) {
2010-02-15 23:43:51 +00:00
return pyrna_prop_array_subscript_slice ( self , & self - > ptr , self - > prop , start , stop , len ) ;
2008-11-29 13:36:08 +00:00
}
2009-07-01 13:31:36 +00:00
else {
PyErr_SetString ( PyExc_TypeError , " slice steps not supported with rna " ) ;
return NULL ;
2008-11-29 13:36:08 +00:00
}
}
2009-07-01 13:31:36 +00:00
else {
PyErr_SetString ( PyExc_AttributeError , " invalid key, key must be an int " ) ;
return NULL ;
}
}
2010-01-02 17:33:44 +00:00
/* could call (pyrna_py_to_prop_index(self, i, value) in a loop but it is slow */
2010-01-04 20:53:52 +00:00
static int prop_subscript_ass_array_slice ( PointerRNA * ptr , PropertyRNA * prop , int start , int stop , int length , PyObject * value_orig )
2009-07-01 13:31:36 +00:00
{
2010-01-04 20:53:52 +00:00
PyObject * value ;
2009-07-01 13:31:36 +00:00
int count ;
2010-01-02 17:33:44 +00:00
void * values_alloc = NULL ;
int ret = 0 ;
2010-01-04 20:53:52 +00:00
if ( value_orig = = NULL ) {
PyErr_SetString ( PyExc_TypeError , " invalid slice assignment, deleting with list types is not supported by StructRNA. " ) ;
return - 1 ;
}
if ( ! ( value = PySequence_Fast ( value_orig , " invalid slice assignment, type is not a sequence " ) ) ) {
return - 1 ;
}
if ( PySequence_Fast_GET_SIZE ( value ) ! = stop - start ) {
Py_DECREF ( value ) ;
PyErr_SetString ( PyExc_TypeError , " invalid slice assignment, resizing StructRNA arrays isn't supported. " ) ;
2010-01-02 17:33:44 +00:00
return - 1 ;
}
switch ( RNA_property_type ( prop ) ) {
case PROP_FLOAT :
{
float values_stack [ PYRNA_STACK_ARRAY ] ;
2010-02-21 14:48:28 +00:00
float * values , fval ;
float min , max ;
RNA_property_float_range ( ptr , prop , & min , & max ) ;
2010-01-02 17:33:44 +00:00
if ( length > PYRNA_STACK_ARRAY ) { values = values_alloc = PyMem_MALLOC ( sizeof ( float ) * length ) ; }
else { values = values_stack ; }
if ( start ! = 0 | | stop ! = length ) /* partial assignment? - need to get the array */
RNA_property_float_get_array ( ptr , prop , values ) ;
2010-02-21 14:48:28 +00:00
for ( count = start ; count < stop ; count + + ) {
fval = PyFloat_AsDouble ( PySequence_Fast_GET_ITEM ( value , count - start ) ) ;
CLAMP ( fval , min , max ) ;
values [ count ] = fval ;
}
2010-01-02 17:33:44 +00:00
if ( PyErr_Occurred ( ) ) ret = - 1 ;
else RNA_property_float_set_array ( ptr , prop , values ) ;
break ;
}
case PROP_BOOLEAN :
{
int values_stack [ PYRNA_STACK_ARRAY ] ;
int * values ;
if ( length > PYRNA_STACK_ARRAY ) { values = values_alloc = PyMem_MALLOC ( sizeof ( int ) * length ) ; }
else { values = values_stack ; }
if ( start ! = 0 | | stop ! = length ) /* partial assignment? - need to get the array */
RNA_property_boolean_get_array ( ptr , prop , values ) ;
for ( count = start ; count < stop ; count + + )
2010-01-04 20:53:52 +00:00
values [ count ] = PyLong_AsSsize_t ( PySequence_Fast_GET_ITEM ( value , count - start ) ) ;
2010-01-02 17:33:44 +00:00
if ( PyErr_Occurred ( ) ) ret = - 1 ;
else RNA_property_boolean_set_array ( ptr , prop , values ) ;
break ;
}
case PROP_INT :
{
int values_stack [ PYRNA_STACK_ARRAY ] ;
2010-02-21 14:48:28 +00:00
int * values , ival ;
int min , max ;
RNA_property_int_range ( ptr , prop , & min , & max ) ;
2010-01-02 17:33:44 +00:00
if ( length > PYRNA_STACK_ARRAY ) { values = values_alloc = PyMem_MALLOC ( sizeof ( int ) * length ) ; }
else { values = values_stack ; }
if ( start ! = 0 | | stop ! = length ) /* partial assignment? - need to get the array */
RNA_property_int_get_array ( ptr , prop , values ) ;
2009-07-01 13:31:36 +00:00
2010-02-21 14:48:28 +00:00
for ( count = start ; count < stop ; count + + ) {
ival = PyLong_AsSsize_t ( PySequence_Fast_GET_ITEM ( value , count - start ) ) ;
CLAMP ( ival , min , max ) ;
values [ count ] = ival ;
}
2008-11-29 17:58:17 +00:00
2010-01-02 17:33:44 +00:00
if ( PyErr_Occurred ( ) ) ret = - 1 ;
else RNA_property_int_set_array ( ptr , prop , values ) ;
break ;
2009-07-01 13:31:36 +00:00
}
2010-01-02 17:33:44 +00:00
default :
PyErr_SetString ( PyExc_TypeError , " not an array type " ) ;
ret = - 1 ;
2009-07-01 13:31:36 +00:00
}
2010-01-04 20:53:52 +00:00
Py_DECREF ( value ) ;
2010-01-02 17:33:44 +00:00
if ( values_alloc ) {
PyMem_FREE ( values_alloc ) ;
}
return ret ;
2009-07-01 13:31:36 +00:00
}
2010-02-15 23:43:51 +00:00
static int prop_subscript_ass_array_int ( BPy_PropertyRNA * self , Py_ssize_t keynum , PyObject * value )
2008-11-29 17:58:17 +00:00
{
2009-09-06 15:13:57 +00:00
int len = pyrna_prop_array_length ( self ) ;
2009-07-01 13:31:36 +00:00
if ( keynum < 0 ) keynum + = len ;
if ( keynum > = 0 & & keynum < len )
2009-09-06 15:13:57 +00:00
return pyrna_py_to_prop_index ( self , keynum , value ) ;
2009-07-01 13:31:36 +00:00
PyErr_SetString ( PyExc_IndexError , " out of range " ) ;
return - 1 ;
}
2010-02-15 23:43:51 +00:00
static int pyrna_prop_array_ass_subscript ( BPy_PropertyRNA * self , PyObject * key , PyObject * value )
2009-07-01 13:31:36 +00:00
{
/* char *keyname = NULL; */ /* not supported yet */
2008-11-29 17:58:17 +00:00
2008-11-30 03:52:07 +00:00
if ( ! RNA_property_editable ( & self - > ptr , self - > prop ) ) {
2009-07-09 08:06:26 +00:00
PyErr_Format ( PyExc_AttributeError , " PropertyRNA - attribute \" %.200s \" from \" %.200s \" is read-only " , RNA_property_identifier ( self - > prop ) , RNA_struct_identifier ( self - > ptr . type ) ) ;
2008-11-30 03:52:07 +00:00
return - 1 ;
}
2009-07-01 13:31:36 +00:00
2009-07-08 09:23:49 +00:00
if ( PyIndex_Check ( key ) ) {
Py_ssize_t i = PyNumber_AsSsize_t ( key , PyExc_IndexError ) ;
if ( i = = - 1 & & PyErr_Occurred ( ) )
2009-07-09 08:06:26 +00:00
return - 1 ;
2009-07-08 09:23:49 +00:00
return prop_subscript_ass_array_int ( self , i , value ) ;
2009-07-01 13:31:36 +00:00
}
else if ( PySlice_Check ( key ) ) {
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]
2009-08-25 17:06:36 +00:00
int len = RNA_property_array_length ( & self - > ptr , self - > prop ) ;
2009-07-01 13:31:36 +00:00
Py_ssize_t start , stop , step , slicelength ;
if ( PySlice_GetIndicesEx ( ( PySliceObject * ) key , len , & start , & stop , & step , & slicelength ) < 0 )
return - 1 ;
if ( slicelength < = 0 ) {
return 0 ;
2008-11-29 17:58:17 +00:00
}
2009-07-01 13:31:36 +00:00
else if ( step = = 1 ) {
2010-01-02 17:33:44 +00:00
return prop_subscript_ass_array_slice ( & self - > ptr , self - > prop , start , stop , len , value ) ;
2009-07-01 13:31:36 +00:00
}
else {
PyErr_SetString ( PyExc_TypeError , " slice steps not supported with rna " ) ;
return - 1 ;
2008-11-29 17:58:17 +00:00
}
}
2009-07-01 13:31:36 +00:00
else {
PyErr_SetString ( PyExc_AttributeError , " invalid key, key must be an int " ) ;
return - 1 ;
}
2010-01-27 17:23:28 +00:00
RNA_property_update ( BPy_GetContext ( ) , & self - > ptr , self - > prop ) ;
2008-11-29 17:58:17 +00:00
}
2010-02-15 23:43:51 +00:00
/* for slice only */
static PyMappingMethods pyrna_prop_array_as_mapping = {
( lenfunc ) pyrna_prop_array_length , /* mp_length */
( binaryfunc ) pyrna_prop_array_subscript , /* mp_subscript */
( objobjargproc ) pyrna_prop_array_ass_subscript , /* mp_ass_subscript */
} ;
2008-11-29 17:58:17 +00:00
2010-02-15 23:43:51 +00:00
static PyMappingMethods pyrna_prop_collection_as_mapping = {
( lenfunc ) pyrna_prop_collection_length , /* mp_length */
( binaryfunc ) pyrna_prop_collection_subscript , /* mp_subscript */
( objobjargproc ) NULL , /* mp_ass_subscript */
2008-11-29 13:36:08 +00:00
} ;
2009-11-16 19:03:40 +00:00
2010-02-15 23:43:51 +00:00
static int pyrna_prop_array_contains ( BPy_PropertyRNA * self , PyObject * value )
{
return pyrna_array_contains_py ( & self - > ptr , self - > prop , value ) ;
}
2009-11-16 19:03:40 +00:00
2010-02-15 23:43:51 +00:00
static int pyrna_prop_collection_contains ( BPy_PropertyRNA * self , PyObject * value )
{
PointerRNA newptr ; /* not used, just so RNA_property_collection_lookup_string runs */
2009-11-16 19:03:40 +00:00
2010-02-15 23:43:51 +00:00
/* key in dict style check */
char * keyname = _PyUnicode_AsString ( value ) ;
2009-11-16 19:03:40 +00:00
2010-02-15 23:43:51 +00:00
if ( keyname = = NULL ) {
PyErr_SetString ( PyExc_TypeError , " PropertyRNA - key in prop, key must be a string type " ) ;
2009-12-08 09:40:30 +00:00
return - 1 ;
}
2009-11-16 19:03:40 +00:00
2010-02-15 23:43:51 +00:00
if ( RNA_property_collection_lookup_string ( & self - > ptr , self - > prop , keyname , & newptr ) )
return 1 ;
2009-06-13 08:04:43 +00:00
return 0 ;
}
2009-11-16 19:03:40 +00:00
static int pyrna_struct_contains ( BPy_StructRNA * self , PyObject * value )
{
IDProperty * group ;
char * name = _PyUnicode_AsString ( value ) ;
if ( ! name ) {
PyErr_SetString ( PyExc_TypeError , " expected a string " ) ;
return - 1 ;
}
2009-12-24 11:40:14 +00:00
if ( RNA_struct_idproperties_check ( self - > ptr . type ) = = 0 ) {
2009-11-16 19:03:40 +00:00
PyErr_SetString ( PyExc_TypeError , " this type doesnt support IDProperties " ) ;
return - 1 ;
}
group = RNA_struct_idproperties ( & self - > ptr , 0 ) ;
if ( ! group )
return 0 ;
return IDP_GetPropertyFromGroup ( group , name ) ? 1 : 0 ;
}
2010-02-15 23:43:51 +00:00
static PySequenceMethods pyrna_prop_array_as_sequence = {
( lenfunc ) pyrna_prop_array_length , /* Cant set the len otherwise it can evaluate as false */
2009-06-13 08:04:43 +00:00
NULL , /* sq_concat */
NULL , /* sq_repeat */
2010-02-15 23:43:51 +00:00
( ssizeargfunc ) pyrna_prop_array_subscript_int , /* sq_item */ /* Only set this so PySequence_Check() returns True */
2009-06-13 08:04:43 +00:00
NULL , /* sq_slice */
2010-02-15 23:43:51 +00:00
( ssizeobjargproc ) prop_subscript_ass_array_int , /* sq_ass_item */
NULL , /* *was* sq_ass_slice */
( objobjproc ) pyrna_prop_array_contains , /* sq_contains */
} ;
static PySequenceMethods pyrna_prop_collection_as_sequence = {
( lenfunc ) pyrna_prop_collection_length , /* Cant set the len otherwise it can evaluate as false */
NULL , /* sq_concat */
NULL , /* sq_repeat */
( ssizeargfunc ) pyrna_prop_collection_subscript_int , /* sq_item */ /* Only set this so PySequence_Check() returns True */
NULL , /* *was* sq_slice */
2009-06-13 08:04:43 +00:00
NULL , /* sq_ass_item */
2010-02-15 23:43:51 +00:00
NULL , /* *was* sq_ass_slice */
( objobjproc ) pyrna_prop_collection_contains , /* sq_contains */
2009-06-13 08:04:43 +00:00
} ;
2009-11-16 19:03:40 +00:00
static PySequenceMethods pyrna_struct_as_sequence = {
NULL , /* Cant set the len otherwise it can evaluate as false */
NULL , /* sq_concat */
NULL , /* sq_repeat */
NULL , /* sq_item */ /* Only set this so PySequence_Check() returns True */
2010-02-15 23:43:51 +00:00
NULL , /* *was* sq_slice */
2009-11-16 19:03:40 +00:00
NULL , /* sq_ass_item */
2010-02-15 23:43:51 +00:00
NULL , /* *was* sq_ass_slice */
2009-11-16 19:03:40 +00:00
( objobjproc ) pyrna_struct_contains , /* sq_contains */
} ;
2009-07-08 09:23:49 +00:00
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_struct_subscript ( BPy_StructRNA * self , PyObject * key )
{
/* mostly copied from BPy_IDGroup_Map_GetItem */
IDProperty * group , * idprop ;
char * name = _PyUnicode_AsString ( key ) ;
2009-12-24 11:40:14 +00:00
if ( RNA_struct_idproperties_check ( self - > ptr . type ) = = 0 ) {
2009-11-17 12:21:41 +00:00
PyErr_SetString ( PyExc_TypeError , " this type doesn't support IDProperties " ) ;
return NULL ;
}
2009-11-16 19:03:40 +00:00
if ( name = = NULL ) {
PyErr_SetString ( PyExc_TypeError , " only strings are allowed as keys of ID properties " ) ;
return NULL ;
}
group = RNA_struct_idproperties ( & self - > ptr , 0 ) ;
if ( group = = NULL ) {
2009-11-18 13:02:09 +00:00
PyErr_Format ( PyExc_KeyError , " key \" %s \" not found " , name ) ;
2009-11-16 19:03:40 +00:00
return NULL ;
}
idprop = IDP_GetPropertyFromGroup ( group , name ) ;
if ( idprop = = NULL ) {
2009-11-18 13:02:09 +00:00
PyErr_Format ( PyExc_KeyError , " key \" %s \" not found " , name ) ;
2009-11-16 19:03:40 +00:00
return NULL ;
}
return BPy_IDGroup_WrapData ( self - > ptr . id . data , idprop ) ;
}
static int pyrna_struct_ass_subscript ( BPy_StructRNA * self , PyObject * key , PyObject * value )
{
2009-11-16 22:21:39 +00:00
IDProperty * group = RNA_struct_idproperties ( & self - > ptr , 1 ) ;
2009-11-16 19:03:40 +00:00
if ( group = = NULL ) {
PyErr_SetString ( PyExc_TypeError , " id properties not supported for this type " ) ;
return - 1 ;
}
2009-11-16 22:21:39 +00:00
return BPy_Wrap_SetMapItem ( group , key , value ) ;
2009-11-16 19:03:40 +00:00
}
static PyMappingMethods pyrna_struct_as_mapping = {
( lenfunc ) NULL , /* mp_length */
( binaryfunc ) pyrna_struct_subscript , /* mp_subscript */
( objobjargproc ) pyrna_struct_ass_subscript , /* mp_ass_subscript */
} ;
2009-11-16 20:16:45 +00:00
static PyObject * pyrna_struct_keys ( BPy_PropertyRNA * self )
{
IDProperty * group ;
2009-12-24 11:40:14 +00:00
if ( RNA_struct_idproperties_check ( self - > ptr . type ) = = 0 ) {
2009-11-16 20:16:45 +00:00
PyErr_SetString ( PyExc_TypeError , " this type doesnt support IDProperties " ) ;
return NULL ;
}
group = RNA_struct_idproperties ( & self - > ptr , 0 ) ;
if ( group = = NULL )
return PyList_New ( 0 ) ;
return BPy_Wrap_GetKeys ( group ) ;
}
static PyObject * pyrna_struct_items ( BPy_PropertyRNA * self )
{
IDProperty * group ;
2009-12-24 11:40:14 +00:00
if ( RNA_struct_idproperties_check ( self - > ptr . type ) = = 0 ) {
2009-11-16 20:16:45 +00:00
PyErr_SetString ( PyExc_TypeError , " this type doesnt support IDProperties " ) ;
return NULL ;
}
group = RNA_struct_idproperties ( & self - > ptr , 0 ) ;
if ( group = = NULL )
return PyList_New ( 0 ) ;
return BPy_Wrap_GetItems ( self - > ptr . id . data , group ) ;
}
static PyObject * pyrna_struct_values ( BPy_PropertyRNA * self )
{
IDProperty * group ;
2009-12-24 11:40:14 +00:00
if ( RNA_struct_idproperties_check ( self - > ptr . type ) = = 0 ) {
2009-11-16 20:16:45 +00:00
PyErr_SetString ( PyExc_TypeError , " this type doesnt support IDProperties " ) ;
return NULL ;
}
group = RNA_struct_idproperties ( & self - > ptr , 0 ) ;
if ( group = = NULL )
return PyList_New ( 0 ) ;
return BPy_Wrap_GetValues ( self - > ptr . id . data , group ) ;
}
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_struct_keyframe_insert ( BPy_StructRNA * self , PyObject * args )
2009-07-08 09:23:49 +00:00
{
2009-10-30 17:23:40 +00:00
char * path , * path_full ;
2009-11-04 14:06:10 +00:00
int index = - 1 ; /* default to all */
2009-07-08 09:23:49 +00:00
float cfra = CTX_data_scene ( BPy_GetContext ( ) ) - > r . cfra ;
2009-10-30 17:23:40 +00:00
PropertyRNA * prop ;
PyObject * result ;
2009-07-08 09:23:49 +00:00
2009-10-30 17:23:40 +00:00
if ( ! PyArg_ParseTuple ( args , " s|if:keyframe_insert " , & path , & index , & cfra ) )
return NULL ;
if ( self - > ptr . data = = NULL ) {
PyErr_Format ( PyExc_TypeError , " keyframe_insert, this struct has no data, cant be animated " , path ) ;
2009-07-08 09:23:49 +00:00
return NULL ;
}
2009-10-30 17:23:40 +00:00
prop = RNA_struct_find_property ( & self - > ptr , path ) ;
if ( prop = = NULL ) {
PyErr_Format ( PyExc_TypeError , " keyframe_insert, property \" %s \" not found " , path ) ;
return NULL ;
}
if ( ! RNA_property_animateable ( & self - > ptr , prop ) ) {
PyErr_Format ( PyExc_TypeError , " keyframe_insert, property \" %s \" not animatable " , path ) ;
2009-07-08 09:23:49 +00:00
return NULL ;
2009-10-30 17:23:40 +00:00
}
path_full = RNA_path_from_ID_to_property ( & self - > ptr , prop ) ;
if ( path_full = = NULL ) {
PyErr_Format ( PyExc_TypeError , " keyframe_insert, could not make path to \" %s \" " , path ) ;
return NULL ;
}
2009-07-08 09:23:49 +00:00
2009-10-30 17:23:40 +00:00
result = PyBool_FromLong ( insert_keyframe ( ( ID * ) self - > ptr . id . data , NULL , NULL , path_full , index , cfra , 0 ) ) ;
MEM_freeN ( path_full ) ;
return result ;
2009-07-08 09:23:49 +00:00
}
2009-11-04 15:16:41 +00:00
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_struct_driver_add ( BPy_StructRNA * self , PyObject * args )
2009-11-04 15:16:41 +00:00
{
char * path , * path_full ;
int index = - 1 ; /* default to all */
PropertyRNA * prop ;
2009-11-25 10:13:24 +00:00
PyObject * ret ;
2009-11-04 15:16:41 +00:00
if ( ! PyArg_ParseTuple ( args , " s|i:driver_add " , & path , & index ) )
return NULL ;
if ( self - > ptr . data = = NULL ) {
PyErr_Format ( PyExc_TypeError , " driver_add, this struct has no data, cant be animated " , path ) ;
return NULL ;
}
prop = RNA_struct_find_property ( & self - > ptr , path ) ;
if ( prop = = NULL ) {
PyErr_Format ( PyExc_TypeError , " driver_add, property \" %s \" not found " , path ) ;
return NULL ;
}
if ( ! RNA_property_animateable ( & self - > ptr , prop ) ) {
PyErr_Format ( PyExc_TypeError , " driver_add, property \" %s \" not animatable " , path ) ;
return NULL ;
}
path_full = RNA_path_from_ID_to_property ( & self - > ptr , prop ) ;
if ( path_full = = NULL ) {
PyErr_Format ( PyExc_TypeError , " driver_add, could not make path to \" %s \" " , path ) ;
return NULL ;
}
2009-11-25 10:13:24 +00:00
if ( ANIM_add_driver ( ( ID * ) self - > ptr . id . data , path_full , index , 0 , DRIVER_TYPE_PYTHON ) ) {
ID * id = self - > ptr . id . data ;
AnimData * adt = BKE_animdata_from_id ( id ) ;
FCurve * fcu ;
PointerRNA tptr ;
PyObject * item ;
if ( index = = - 1 ) { /* all, use a list */
int i = 0 ;
ret = PyList_New ( 0 ) ;
while ( ( fcu = list_find_fcurve ( & adt - > drivers , path_full , i + + ) ) ) {
RNA_pointer_create ( id , & RNA_FCurve , fcu , & tptr ) ;
item = pyrna_struct_CreatePyObject ( & tptr ) ;
PyList_Append ( ret , item ) ;
Py_DECREF ( item ) ;
}
}
else {
fcu = list_find_fcurve ( & adt - > drivers , path_full , index ) ;
RNA_pointer_create ( id , & RNA_FCurve , fcu , & tptr ) ;
ret = pyrna_struct_CreatePyObject ( & tptr ) ;
}
}
else {
ret = Py_None ;
Py_INCREF ( ret ) ;
}
2009-11-04 15:16:41 +00:00
MEM_freeN ( path_full ) ;
2009-11-25 10:13:24 +00:00
return ret ;
2009-11-04 15:16:41 +00:00
}
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_struct_is_property_set ( BPy_StructRNA * self , PyObject * args )
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
{
char * name ;
if ( ! PyArg_ParseTuple ( args , " s:is_property_set " , & name ) )
return NULL ;
return PyBool_FromLong ( RNA_property_is_set ( & self - > ptr , name ) ) ;
}
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_struct_is_property_hidden ( BPy_StructRNA * self , PyObject * args )
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
{
PropertyRNA * prop ;
char * name ;
int hidden ;
if ( ! PyArg_ParseTuple ( args , " s:is_property_hidden " , & name ) )
return NULL ;
prop = RNA_struct_find_property ( & self - > ptr , name ) ;
hidden = ( prop ) ? ( RNA_property_flag ( prop ) & PROP_HIDDEN ) : 1 ;
return PyBool_FromLong ( hidden ) ;
}
2009-11-17 20:46:59 +00:00
static PyObject * pyrna_struct_path_resolve ( BPy_StructRNA * self , PyObject * value )
{
char * path = _PyUnicode_AsString ( value ) ;
PointerRNA r_ptr ;
PropertyRNA * r_prop ;
if ( path = = NULL ) {
PyErr_SetString ( PyExc_TypeError , " items() is only valid for collection types " ) ;
return NULL ;
}
if ( RNA_path_resolve ( & self - > ptr , path , & r_ptr , & r_prop ) )
return pyrna_prop_CreatePyObject ( & r_ptr , r_prop ) ;
Py_RETURN_NONE ;
}
2009-11-23 23:17:23 +00:00
static PyObject * pyrna_struct_path_to_id ( BPy_StructRNA * self , PyObject * args )
{
char * name = NULL ;
char * path ;
PropertyRNA * prop ;
PyObject * ret ;
if ( ! PyArg_ParseTuple ( args , " |s:path_to_id " , & name ) )
return NULL ;
if ( name ) {
prop = RNA_struct_find_property ( & self - > ptr , name ) ;
if ( prop = = NULL ) {
PyErr_Format ( PyExc_TypeError , " path_to_id( \" %.200s \" ) not found " , name ) ;
return NULL ;
}
path = RNA_path_from_ID_to_property ( & self - > ptr , prop ) ;
}
else {
path = RNA_path_from_ID_to_struct ( & self - > ptr ) ;
}
if ( path = = NULL ) {
if ( name ) PyErr_Format ( PyExc_TypeError , " %.200s.path_to_id( \" %s \" ) found but does not support path creation " , RNA_struct_identifier ( self - > ptr . type ) , name ) ;
else PyErr_Format ( PyExc_TypeError , " %.200s.path_to_id() does not support path creation for this type " , name) ;
return NULL ;
}
ret = PyUnicode_FromString ( path ) ;
MEM_freeN ( path ) ;
return ret ;
}
2010-01-17 20:06:34 +00:00
static PyObject * pyrna_struct_recast_type ( BPy_StructRNA * self , PyObject * args )
{
PointerRNA r_ptr ;
RNA_pointer_recast ( & self - > ptr , & r_ptr ) ;
return pyrna_struct_CreatePyObject ( & r_ptr ) ;
}
2009-11-23 23:17:23 +00:00
static PyObject * pyrna_prop_path_to_id ( BPy_PropertyRNA * self )
{
char * path ;
2009-11-25 09:25:58 +00:00
PropertyRNA * prop = self - > prop ;
2009-11-23 23:17:23 +00:00
PyObject * ret ;
path = RNA_path_from_ID_to_property ( & self - > ptr , self - > prop ) ;
if ( path = = NULL ) {
PyErr_Format ( PyExc_TypeError , " %.200s.%.200s.path_to_id() does not support path creation for this type " , RNA_struct_identifier ( self - > ptr . type ) , RNA_property_identifier ( prop ) ) ;
return NULL ;
}
ret = PyUnicode_FromString ( path ) ;
MEM_freeN ( path ) ;
return ret ;
}
2009-11-20 10:00:54 +00:00
static void pyrna_dir_members_py ( PyObject * list , PyObject * self )
{
PyObject * dict ;
PyObject * * dict_ptr ;
PyObject * list_tmp ;
dict_ptr = _PyObject_GetDictPtr ( ( PyObject * ) self ) ;
if ( dict_ptr & & ( dict = * dict_ptr ) ) {
list_tmp = PyDict_Keys ( dict ) ;
PyList_SetSlice ( list , INT_MAX , INT_MAX , list_tmp ) ;
Py_DECREF ( list_tmp ) ;
}
dict = ( ( PyTypeObject * ) Py_TYPE ( self ) ) - > tp_dict ;
if ( dict ) {
list_tmp = PyDict_Keys ( dict ) ;
PyList_SetSlice ( list , INT_MAX , INT_MAX , list_tmp ) ;
Py_DECREF ( list_tmp ) ;
}
}
static void pyrna_dir_members_rna ( PyObject * list , PointerRNA * ptr )
2008-11-30 14:00:14 +00:00
{
2009-03-21 06:55:30 +00:00
PyObject * pystring ;
2009-11-20 10:00:54 +00:00
const char * idname ;
2009-04-09 16:52:18 +00:00
/* for looping over attrs and funcs */
2009-11-20 10:00:54 +00:00
PointerRNA tptr ;
2009-04-09 16:52:18 +00:00
PropertyRNA * iterprop ;
2009-03-21 06:55:30 +00:00
2009-11-20 10:00:54 +00:00
{
RNA_pointer_create ( NULL , & RNA_Struct , ptr - > type , & tptr ) ;
iterprop = RNA_struct_find_property ( & tptr , " functions " ) ;
2009-03-21 06:55:30 +00:00
2009-11-20 10:00:54 +00:00
RNA_PROP_BEGIN ( & tptr , itemptr , iterprop ) {
idname = RNA_function_identifier ( itemptr . data ) ;
2009-11-19 18:22:21 +00:00
2009-11-20 10:00:54 +00:00
pystring = PyUnicode_FromString ( idname ) ;
PyList_Append ( list , pystring ) ;
Py_DECREF ( pystring ) ;
}
RNA_PROP_END ;
2009-03-05 12:09:30 +00:00
}
2009-11-20 10:00:54 +00:00
2009-03-11 17:28:37 +00:00
{
2009-04-09 16:52:18 +00:00
/*
* Collect RNA attributes
*/
2009-03-05 12:09:30 +00:00
char name [ 256 ] , * nameptr ;
2009-11-20 10:00:54 +00:00
iterprop = RNA_struct_iterator_property ( ptr - > type ) ;
2009-03-05 12:09:30 +00:00
2009-11-20 10:00:54 +00:00
RNA_PROP_BEGIN ( ptr , itemptr , iterprop ) {
2009-06-24 21:27:10 +00:00
nameptr = RNA_struct_name_get_alloc ( & itemptr , name , sizeof ( name ) ) ;
2009-06-24 14:03:55 +00:00
if ( nameptr ) {
2009-11-13 16:08:03 +00:00
pystring = PyUnicode_FromString ( nameptr ) ;
2009-11-20 10:00:54 +00:00
PyList_Append ( list , pystring ) ;
2009-11-13 16:08:03 +00:00
Py_DECREF ( pystring ) ;
2009-06-24 14:03:55 +00:00
if ( name ! = nameptr )
2009-03-05 12:09:30 +00:00
MEM_freeN ( nameptr ) ;
}
2008-11-29 13:36:08 +00:00
}
2009-06-24 21:27:10 +00:00
RNA_PROP_END ;
2009-04-09 16:52:18 +00:00
}
2009-11-20 10:00:54 +00:00
}
2009-04-09 16:52:18 +00:00
2009-11-20 10:00:54 +00:00
static PyObject * pyrna_struct_dir ( BPy_StructRNA * self )
{
PyObject * ret ;
PyObject * pystring ;
2009-11-11 17:12:48 +00:00
2009-11-20 10:00:54 +00:00
/* 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
* */
ret = PyList_New ( 0 ) ;
if ( ! BPy_StructRNA_CheckExact ( self ) )
pyrna_dir_members_py ( ret , ( PyObject * ) self ) ;
pyrna_dir_members_rna ( ret , & self - > ptr ) ;
2009-06-20 14:55:28 +00:00
if ( self - > ptr . type = = & RNA_Context ) {
ListBase lb = CTX_data_dir_get ( self - > ptr . data ) ;
LinkData * link ;
for ( link = lb . first ; link ; link = link - > next ) {
pystring = PyUnicode_FromString ( link - > data ) ;
PyList_Append ( ret , pystring ) ;
Py_DECREF ( pystring ) ;
}
BLI_freelistN ( & lb ) ;
}
2009-03-11 17:28:37 +00:00
return ret ;
}
//---------------getattr--------------------------------------------
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_struct_getattro ( BPy_StructRNA * self , PyObject * pyname )
2009-03-11 17:28:37 +00:00
{
char * name = _PyUnicode_AsString ( pyname ) ;
PyObject * ret ;
PropertyRNA * prop ;
2009-04-07 00:49:39 +00:00
FunctionRNA * func ;
2009-03-11 17:28:37 +00:00
2009-11-14 23:11:46 +00:00
if ( name [ 0 ] = = ' _ ' ) { // rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups
2009-11-17 12:21:41 +00:00
/* annoying exception, maybe we need to have different types for this... */
2009-12-24 11:40:14 +00:00
if ( ( strcmp ( name , " __getitem__ " ) = = 0 | | strcmp ( name , " __setitem__ " ) = = 0 ) & & ! RNA_struct_idproperties_check ( self - > ptr . type ) ) {
2009-11-17 12:21:41 +00:00
PyErr_SetString ( PyExc_AttributeError , " StructRNA - no __getitem__ support for this type " ) ;
ret = NULL ;
}
else {
ret = PyObject_GenericGetAttr ( ( PyObject * ) self , pyname ) ;
}
2009-11-14 23:11:46 +00:00
}
else if ( ( prop = RNA_struct_find_property ( & self - > ptr , name ) ) ) {
2009-04-07 00:49:39 +00:00
ret = pyrna_prop_to_py ( & self - > ptr , prop ) ;
}
2009-12-28 22:48:10 +00:00
/* RNA function only if callback is declared (no optional functions) */
else if ( ( func = RNA_struct_find_function ( & self - > ptr , name ) ) & & RNA_function_defined ( func ) ) {
2009-11-11 16:28:53 +00:00
ret = pyrna_func_to_py ( ( BPy_DummyPointerRNA * ) self , func ) ;
2009-03-11 17:28:37 +00:00
}
2009-04-07 00:49:39 +00:00
else if ( self - > ptr . type = = & RNA_Context ) {
2010-01-27 10:54:11 +00:00
bContext * C = self - > ptr . data ;
if ( C = = NULL ) {
PyErr_Format ( PyExc_AttributeError , " StructRNA Context is 'NULL', can't get \" %.200s \" from context " , name ) ;
ret = NULL ;
}
else {
PointerRNA newptr ;
ListBase newlb ;
2009-03-19 19:03:38 +00:00
2010-01-27 10:54:11 +00:00
int done = CTX_data_get ( C , name , & newptr , & newlb ) ;
2009-03-19 19:03:38 +00:00
2010-01-27 10:54:11 +00:00
if ( done = = 1 ) { /* found */
if ( newptr . data ) {
ret = pyrna_struct_CreatePyObject ( & newptr ) ;
}
else if ( newlb . first ) {
CollectionPointerLink * link ;
PyObject * linkptr ;
2009-03-19 19:03:38 +00:00
2010-01-27 10:54:11 +00:00
ret = PyList_New ( 0 ) ;
2009-03-19 19:03:38 +00:00
2010-01-27 10:54:11 +00:00
for ( link = newlb . first ; link ; link = link - > next ) {
linkptr = pyrna_struct_CreatePyObject ( & link - > ptr ) ;
PyList_Append ( ret , linkptr ) ;
Py_DECREF ( linkptr ) ;
}
}
else {
ret = Py_None ;
Py_INCREF ( ret ) ;
2009-11-10 15:09:53 +00:00
}
}
2010-01-27 10:54:11 +00:00
else if ( done = = - 1 ) { /* found but not set */
2009-11-10 15:09:53 +00:00
ret = Py_None ;
Py_INCREF ( ret ) ;
2009-03-19 19:03:38 +00:00
}
2010-01-27 10:54:11 +00:00
else { /* not found in the context */
/* lookup the subclass. raise an error if its not found */
ret = PyObject_GenericGetAttr ( ( PyObject * ) self , pyname ) ;
}
2009-03-19 19:03:38 +00:00
2010-01-27 10:54:11 +00:00
BLI_freelistN ( & newlb ) ;
}
2009-03-19 19:03:38 +00:00
}
2009-03-05 12:09:30 +00:00
else {
2009-11-08 01:13:19 +00:00
#if 0
2009-07-09 08:06:26 +00:00
PyErr_Format ( PyExc_AttributeError , " StructRNA - Attribute \" %.200s \" not found " , name ) ;
2009-03-05 12:09:30 +00:00
ret = NULL ;
2009-11-08 01:13:19 +00:00
# endif
/* 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
*
* Also needed to return methods when its not a subtype
* */
/* The error raised here will be displayed */
ret = PyObject_GenericGetAttr ( ( PyObject * ) self , pyname ) ;
2008-11-29 13:36:08 +00:00
}
2008-11-29 17:58:17 +00:00
return ret ;
}
2008-11-29 13:36:08 +00:00
2009-11-19 18:22:21 +00:00
#if 0
static int pyrna_struct_pydict_contains ( PyObject * self , PyObject * pyname )
{
PyObject * dict = * ( _PyObject_GetDictPtr ( ( PyObject * ) self ) ) ;
if ( dict = = NULL ) /* unlikely */
return 0 ;
return PyDict_Contains ( dict , pyname ) ;
}
# endif
2008-11-29 17:58:17 +00:00
//--------------- setattr-------------------------------------------
2009-11-16 19:03:40 +00:00
static int pyrna_struct_setattro ( BPy_StructRNA * self , PyObject * pyname , PyObject * value )
2008-11-29 17:58:17 +00:00
{
2008-12-01 16:59:18 +00:00
char * name = _PyUnicode_AsString ( pyname ) ;
2008-11-30 03:52:07 +00:00
PropertyRNA * prop = RNA_struct_find_property ( & self - > ptr , name ) ;
2008-11-29 17:58:17 +00:00
if ( prop = = NULL ) {
2009-12-03 21:53:01 +00:00
return PyObject_GenericSetAttr ( ( PyObject * ) self , pyname , value ) ;
#if 0
2009-10-30 17:23:40 +00:00
// XXX - This currently allows anything to be assigned to an rna prop, need to see how this should be used
// but for now it makes porting scripts confusing since it fails silently.
2009-11-18 08:40:18 +00:00
// edit: allowing this for setting classes internal attributes.
2009-11-19 18:22:21 +00:00
// edit: allow this for any attribute that alredy exists as a python attr
if ( ( name [ 0 ] = = ' _ ' /* || pyrna_struct_pydict_contains(self, pyname) */ ) & &
! BPy_StructRNA_CheckExact ( self ) & &
2009-12-03 21:53:01 +00:00
2009-03-16 15:54:43 +00:00
return 0 ;
2009-11-01 21:53:45 +00:00
} else
{
2009-07-09 08:06:26 +00:00
PyErr_Format ( PyExc_AttributeError , " StructRNA - Attribute \" %.200s \" not found " , name ) ;
2009-03-16 15:54:43 +00:00
return - 1 ;
}
2009-12-03 21:53:01 +00:00
# endif
2008-11-30 03:52:07 +00:00
}
2008-11-29 13:36:08 +00:00
2008-11-30 03:52:07 +00:00
if ( ! RNA_property_editable ( & self - > ptr , prop ) ) {
2009-07-09 08:06:26 +00:00
PyErr_Format ( PyExc_AttributeError , " StructRNA - Attribute \" %.200s \" from \" %.200s \" is read-only " , RNA_property_identifier ( prop ) , RNA_struct_identifier ( self - > ptr . type ) ) ;
2008-11-30 03:52:07 +00:00
return - 1 ;
}
/* pyrna_py_to_prop sets its own exceptions */
2010-01-24 10:51:59 +00:00
return pyrna_py_to_prop ( & self - > ptr , prop , NULL , NULL , value , " StructRNA - item.attr = val: " ) ;
2008-11-29 13:36:08 +00:00
}
2009-11-20 10:00:54 +00:00
static PyObject * pyrna_prop_dir ( BPy_PropertyRNA * self )
{
PyObject * ret ;
PointerRNA r_ptr ;
/* 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
* */
ret = PyList_New ( 0 ) ;
if ( ! BPy_PropertyRNA_CheckExact ( self ) )
pyrna_dir_members_py ( ret , ( PyObject * ) self ) ;
if ( RNA_property_collection_type_get ( & self - > ptr , self - > prop , & r_ptr ) )
pyrna_dir_members_rna ( ret , & r_ptr ) ;
return ret ;
}
2010-02-15 23:43:51 +00:00
static PyObject * pyrna_prop_array_getattro ( BPy_PropertyRNA * self , PyObject * pyname )
{
return PyObject_GenericGetAttr ( ( PyObject * ) self , pyname ) ;
}
static PyObject * pyrna_prop_collection_getattro ( BPy_PropertyRNA * self , PyObject * pyname )
2009-11-03 16:07:29 +00:00
{
2009-11-13 16:08:03 +00:00
char * name = _PyUnicode_AsString ( pyname ) ;
2009-11-03 16:07:29 +00:00
2009-11-14 23:11:46 +00:00
if ( name [ 0 ] ! = ' _ ' ) {
2010-02-15 23:43:51 +00:00
PyObject * ret ;
PropertyRNA * prop ;
FunctionRNA * func ;
2009-11-13 16:37:44 +00:00
2010-02-15 23:43:51 +00:00
PointerRNA r_ptr ;
if ( RNA_property_collection_type_get ( & self - > ptr , self - > prop , & r_ptr ) ) {
if ( ( prop = RNA_struct_find_property ( & r_ptr , name ) ) ) {
ret = pyrna_prop_to_py ( & r_ptr , prop ) ;
2009-11-03 16:07:29 +00:00
2010-02-15 23:43:51 +00:00
return ret ;
}
else if ( ( func = RNA_struct_find_function ( & r_ptr , name ) ) ) {
PyObject * self_collection = pyrna_struct_CreatePyObject ( & r_ptr ) ;
ret = pyrna_func_to_py ( ( BPy_DummyPointerRNA * ) self_collection , func ) ;
Py_DECREF ( self_collection ) ;
2009-11-14 23:11:46 +00:00
2010-02-15 23:43:51 +00:00
return ret ;
2009-11-13 16:37:44 +00:00
}
2009-11-13 16:08:03 +00:00
}
2009-11-11 16:28:53 +00:00
}
2009-11-03 16:07:29 +00:00
2009-11-13 16:08:03 +00:00
/* The error raised here will be displayed */
return PyObject_GenericGetAttr ( ( PyObject * ) self , pyname ) ;
2009-11-11 16:28:53 +00:00
}
2009-11-03 16:07:29 +00:00
2009-11-13 16:08:03 +00:00
//--------------- setattr-------------------------------------------
2010-02-15 23:43:51 +00:00
static int pyrna_prop_collection_setattro ( BPy_PropertyRNA * self , PyObject * pyname , PyObject * value )
2009-11-11 16:28:53 +00:00
{
2009-11-13 16:08:03 +00:00
char * name = _PyUnicode_AsString ( pyname ) ;
PropertyRNA * prop ;
2010-02-15 23:43:51 +00:00
PointerRNA r_ptr ;
2009-11-11 16:28:53 +00:00
2010-02-15 23:43:51 +00:00
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 , NULL , value , " BPy_PropertyRNA - Attribute (setattr) : " ) ;
2009-11-13 16:08:03 +00:00
}
2009-11-03 16:07:29 +00:00
}
2009-11-13 16:08:03 +00:00
PyErr_Format ( PyExc_AttributeError , " BPy_PropertyRNA - Attribute \" %.200s \" not found " , name ) ;
return - 1 ;
2009-11-03 16:07:29 +00:00
}
2009-11-11 16:28:53 +00:00
/* odd case, we need to be able return a python method from a tp_getset */
static PyObject * pyrna_prop_add ( BPy_PropertyRNA * self )
2009-11-03 16:07:29 +00:00
{
2009-11-11 16:28:53 +00:00
PointerRNA r_ptr ;
2009-11-03 16:07:29 +00:00
2009-11-11 16:28:53 +00:00
RNA_property_collection_add ( & self - > ptr , self - > prop , & r_ptr ) ;
if ( ! r_ptr . data ) {
PyErr_SetString ( PyExc_TypeError , " add() not supported for this collection " ) ;
return NULL ;
}
else {
return pyrna_struct_CreatePyObject ( & r_ptr ) ;
}
}
2009-11-03 16:07:29 +00:00
2009-11-11 16:28:53 +00:00
static PyObject * pyrna_prop_remove ( BPy_PropertyRNA * self , PyObject * value )
{
PyObject * ret ;
int key = PyLong_AsSsize_t ( value ) ;
if ( key = = - 1 & & PyErr_Occurred ( ) ) {
PyErr_SetString ( PyExc_TypeError , " remove() expected one int argument " ) ;
return NULL ;
}
if ( ! RNA_property_collection_remove ( & self - > ptr , self - > prop , key ) ) {
PyErr_SetString ( PyExc_TypeError , " remove() not supported for this collection " ) ;
return NULL ;
}
ret = Py_None ;
Py_INCREF ( ret ) ;
return ret ;
}
2009-12-13 10:46:34 +00:00
static PyObject * pyrna_struct_get_id_data ( BPy_StructRNA * self )
{
if ( self - > ptr . id . data ) {
PointerRNA id_ptr ;
RNA_id_pointer_create ( ( ID * ) self - > ptr . id . data , & id_ptr ) ;
return pyrna_struct_CreatePyObject ( & id_ptr ) ;
}
Py_RETURN_NONE ;
}
2009-11-11 16:28:53 +00:00
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
2009-11-13 16:08:03 +00:00
#if 0
2009-11-11 16:28:53 +00:00
static PyGetSetDef pyrna_prop_getseters [ ] = {
{ " active " , ( getter ) pyrna_prop_get_active , ( setter ) pyrna_prop_set_active , " " , NULL } ,
{ NULL , NULL , NULL , NULL , NULL } /* Sentinel */
} ;
2009-11-13 16:08:03 +00:00
# endif
2009-11-11 16:28:53 +00:00
2009-12-13 10:46:34 +00:00
static PyGetSetDef pyrna_struct_getseters [ ] = {
{ " id_data " , ( getter ) pyrna_struct_get_id_data , ( setter ) NULL , " The ID data this datablock is from, (not available for all data) " , NULL } ,
{ NULL , NULL , NULL , NULL , NULL } /* Sentinel */
} ;
2009-06-30 12:52:16 +00:00
static PyObject * pyrna_prop_keys ( BPy_PropertyRNA * self )
2008-11-29 13:36:08 +00:00
{
PyObject * ret ;
2009-04-19 13:37:59 +00:00
if ( RNA_property_type ( self - > prop ) ! = PROP_COLLECTION ) {
2008-11-29 13:36:08 +00:00
PyErr_SetString ( PyExc_TypeError , " keys() is only valid for collection types " ) ;
ret = NULL ;
} else {
PyObject * item ;
char name [ 256 ] , * nameptr ;
ret = PyList_New ( 0 ) ;
2009-06-24 21:27:10 +00:00
RNA_PROP_BEGIN ( & self - > ptr , itemptr , self - > prop ) {
nameptr = RNA_struct_name_get_alloc ( & itemptr , name , sizeof ( name ) ) ;
2009-06-24 14:03:55 +00:00
if ( nameptr ) {
2008-11-29 13:36:08 +00:00
/* add to python list */
item = PyUnicode_FromString ( nameptr ) ;
PyList_Append ( ret , item ) ;
Py_DECREF ( item ) ;
/* done */
2009-06-24 14:03:55 +00:00
if ( name ! = nameptr )
2008-11-29 13:36:08 +00:00
MEM_freeN ( nameptr ) ;
}
}
2009-06-24 21:27:10 +00:00
RNA_PROP_END ;
2008-11-29 13:36:08 +00:00
}
return ret ;
}
2009-06-30 12:52:16 +00:00
static PyObject * pyrna_prop_items ( BPy_PropertyRNA * self )
2008-11-29 13:36:08 +00:00
{
PyObject * ret ;
2009-04-19 13:37:59 +00:00
if ( RNA_property_type ( self - > prop ) ! = PROP_COLLECTION ) {
2008-12-01 22:20:18 +00:00
PyErr_SetString ( PyExc_TypeError , " items() is only valid for collection types " ) ;
2008-11-29 13:36:08 +00:00
ret = NULL ;
} else {
PyObject * item ;
char name [ 256 ] , * nameptr ;
2009-06-20 13:53:14 +00:00
int i = 0 ;
2008-11-29 13:36:08 +00:00
ret = PyList_New ( 0 ) ;
2009-06-24 21:27:10 +00:00
RNA_PROP_BEGIN ( & self - > ptr , itemptr , self - > prop ) {
if ( itemptr . data ) {
2008-11-29 13:36:08 +00:00
/* add to python list */
2009-06-20 13:53:14 +00:00
item = PyTuple_New ( 2 ) ;
2009-06-24 21:27:10 +00:00
nameptr = RNA_struct_name_get_alloc ( & itemptr , name , sizeof ( name ) ) ;
2009-06-24 14:03:55 +00:00
if ( nameptr ) {
2009-06-20 13:53:14 +00:00
PyTuple_SET_ITEM ( item , 0 , PyUnicode_FromString ( nameptr ) ) ;
2009-06-24 14:03:55 +00:00
if ( name ! = nameptr )
2009-06-20 13:53:14 +00:00
MEM_freeN ( nameptr ) ;
}
else {
PyTuple_SET_ITEM ( item , 0 , PyLong_FromSsize_t ( i ) ) ; /* a bit strange but better then returning an empty list */
}
2009-06-24 21:27:10 +00:00
PyTuple_SET_ITEM ( item , 1 , pyrna_struct_CreatePyObject ( & itemptr ) ) ;
2009-06-20 13:53:14 +00:00
2008-11-29 13:36:08 +00:00
PyList_Append ( ret , item ) ;
Py_DECREF ( item ) ;
2009-06-20 13:53:14 +00:00
i + + ;
2008-11-29 13:36:08 +00:00
}
}
2009-06-24 21:27:10 +00:00
RNA_PROP_END ;
2008-11-29 13:36:08 +00:00
}
return ret ;
}
2009-06-30 12:52:16 +00:00
static PyObject * pyrna_prop_values ( BPy_PropertyRNA * self )
2008-11-29 13:36:08 +00:00
{
PyObject * ret ;
2009-06-20 13:53:14 +00:00
2009-04-19 13:37:59 +00:00
if ( RNA_property_type ( self - > prop ) ! = PROP_COLLECTION ) {
2008-12-02 15:27:10 +00:00
PyErr_SetString ( PyExc_TypeError , " values() is only valid for collection types " ) ;
2008-11-29 13:36:08 +00:00
ret = NULL ;
} else {
PyObject * item ;
ret = PyList_New ( 0 ) ;
2009-06-24 21:27:10 +00:00
RNA_PROP_BEGIN ( & self - > ptr , itemptr , self - > prop ) {
item = pyrna_struct_CreatePyObject ( & itemptr ) ;
2009-06-20 13:53:14 +00:00
PyList_Append ( ret , item ) ;
Py_DECREF ( item ) ;
2008-11-29 13:36:08 +00:00
}
2009-06-24 21:27:10 +00:00
RNA_PROP_END ;
2008-11-29 13:36:08 +00:00
}
return ret ;
}
2009-11-23 23:17:23 +00:00
static PyObject * pyrna_struct_get ( BPy_StructRNA * self , PyObject * args )
{
IDProperty * group , * idprop ;
char * key ;
PyObject * def = Py_None ;
if ( ! PyArg_ParseTuple ( args , " s|O:get " , & key , & def ) )
return NULL ;
/* mostly copied from BPy_IDGroup_Map_GetItem */
2009-12-24 11:40:14 +00:00
if ( RNA_struct_idproperties_check ( self - > ptr . type ) = = 0 ) {
2009-11-23 23:17:23 +00:00
PyErr_SetString ( PyExc_TypeError , " this type doesn't support IDProperties " ) ;
return NULL ;
}
group = RNA_struct_idproperties ( & self - > ptr , 0 ) ;
if ( group ) {
idprop = IDP_GetPropertyFromGroup ( group , key ) ;
if ( idprop )
return BPy_IDGroup_WrapData ( self - > ptr . id . data , idprop ) ;
}
Py_INCREF ( def ) ;
return def ;
}
2009-07-09 08:06:26 +00:00
static PyObject * pyrna_prop_get ( BPy_PropertyRNA * self , PyObject * args )
{
PointerRNA newptr ;
char * key ;
PyObject * def = Py_None ;
if ( ! PyArg_ParseTuple ( args , " s|O:get " , & key , & def ) )
return NULL ;
if ( RNA_property_collection_lookup_string ( & self - > ptr , self - > prop , key , & newptr ) )
return pyrna_struct_CreatePyObject ( & newptr ) ;
Py_INCREF ( def ) ;
return def ;
}
2009-06-30 12:52:16 +00:00
static void foreach_attr_type ( BPy_PropertyRNA * self , char * attr ,
/* values to assign */
RawPropertyType * raw_type , int * attr_tot , int * attr_signed )
{
PropertyRNA * prop ;
2010-01-04 22:30:09 +00:00
* raw_type = PROP_RAW_UNSET ;
2009-06-30 12:52:16 +00:00
* attr_tot = 0 ;
2009-07-26 18:18:14 +00:00
* attr_signed = FALSE ;
2009-06-30 12:52:16 +00:00
2010-01-05 13:55:51 +00:00
/* note: this is fail with zero length lists, so dont let this get caled in that case */
2009-06-30 12:52:16 +00:00
RNA_PROP_BEGIN ( & self - > ptr , itemptr , self - > prop ) {
prop = RNA_struct_find_property ( & itemptr , attr ) ;
* raw_type = RNA_property_raw_type ( prop ) ;
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]
2009-08-25 17:06:36 +00:00
* attr_tot = RNA_property_array_length ( & itemptr , prop ) ;
2009-07-26 18:18:14 +00:00
* attr_signed = ( RNA_property_subtype ( prop ) = = PROP_UNSIGNED ) ? FALSE : TRUE ;
2009-06-30 12:52:16 +00:00
break ;
}
RNA_PROP_END ;
}
/* pyrna_prop_foreach_get/set both use this */
static int foreach_parse_args (
BPy_PropertyRNA * self , PyObject * args ,
/*values to assign */
char * * attr , PyObject * * seq , int * tot , int * size , RawPropertyType * raw_type , int * attr_tot , int * attr_signed )
{
2009-07-01 13:31:36 +00:00
#if 0
2009-06-30 12:52:16 +00:00
int array_tot ;
int target_tot ;
2009-07-01 13:31:36 +00:00
# endif
2009-06-30 12:52:16 +00:00
2010-01-04 22:30:09 +00:00
* size = * attr_tot = * attr_signed = FALSE ;
* raw_type = PROP_RAW_UNSET ;
2009-06-30 12:52:16 +00:00
if ( ! PyArg_ParseTuple ( args , " sO " , attr , seq ) | | ( ! PySequence_Check ( * seq ) & & PyObject_CheckBuffer ( * seq ) ) ) {
PyErr_SetString ( PyExc_TypeError , " foreach_get(attr, sequence) expects a string and a sequence " ) ;
return - 1 ;
}
* tot = PySequence_Length ( * seq ) ; // TODO - buffer may not be a sequence! array.array() is tho.
if ( * tot > 0 ) {
foreach_attr_type ( self , * attr , raw_type , attr_tot , attr_signed ) ;
* size = RNA_raw_type_sizeof ( * raw_type ) ;
#if 0 // works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks
if ( ( * attr_tot ) < 1 )
* attr_tot = 1 ;
if ( RNA_property_type ( self - > prop ) = = PROP_COLLECTION )
array_tot = RNA_property_collection_length ( & self - > ptr , self - > prop ) ;
else
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]
2009-08-25 17:06:36 +00:00
array_tot = RNA_property_array_length ( & self - > ptr , self - > prop ) ;
2009-06-30 12:52:16 +00:00
target_tot = array_tot * ( * attr_tot ) ;
/* rna_access.c - rna_raw_access(...) uses this same method */
if ( target_tot ! = ( * tot ) ) {
PyErr_Format ( PyExc_TypeError , " foreach_get(attr, sequence) sequence length mismatch given %d, needed %d " , * tot , target_tot ) ;
return - 1 ;
}
# endif
}
2010-01-05 13:55:51 +00:00
/* check 'attr_tot' otherwise we dont know if any values were set
* this isnt ideal because it means running on an empty list may fail silently when its not compatible . */
if ( * size = = 0 & & * attr_tot ! = 0 ) {
2010-01-04 22:30:09 +00:00
PyErr_SetString ( PyExc_AttributeError , " attribute does not support foreach method " ) ;
return - 1 ;
}
2009-06-30 12:52:16 +00:00
return 0 ;
}
static int foreach_compat_buffer ( RawPropertyType raw_type , int attr_signed , const char * format )
{
char f = format ? * format : ' B ' ; /* B is assumed when not set */
switch ( raw_type ) {
case PROP_RAW_CHAR :
if ( attr_signed ) return ( f = = ' b ' ) ? 1 : 0 ;
else return ( f = = ' B ' ) ? 1 : 0 ;
case PROP_RAW_SHORT :
if ( attr_signed ) return ( f = = ' h ' ) ? 1 : 0 ;
else return ( f = = ' H ' ) ? 1 : 0 ;
case PROP_RAW_INT :
if ( attr_signed ) return ( f = = ' i ' ) ? 1 : 0 ;
else return ( f = = ' I ' ) ? 1 : 0 ;
case PROP_RAW_FLOAT :
return ( f = = ' f ' ) ? 1 : 0 ;
case PROP_RAW_DOUBLE :
return ( f = = ' d ' ) ? 1 : 0 ;
2010-01-08 13:52:38 +00:00
case PROP_RAW_UNSET :
return 0 ;
2009-06-30 12:52:16 +00:00
}
return 0 ;
}
static PyObject * foreach_getset ( BPy_PropertyRNA * self , PyObject * args , int set )
{
2009-10-21 17:56:26 +00:00
PyObject * item = NULL ;
2009-11-11 10:51:40 +00:00
int i = 0 , ok = 0 , buffer_is_compat ;
2009-06-30 12:52:16 +00:00
void * array = NULL ;
/* get/set both take the same args currently */
char * attr ;
PyObject * seq ;
int tot , size , attr_tot , attr_signed ;
RawPropertyType raw_type ;
if ( foreach_parse_args ( self , args , & attr , & seq , & tot , & size , & raw_type , & attr_tot , & attr_signed ) < 0 )
return NULL ;
if ( tot = = 0 )
Py_RETURN_NONE ;
if ( set ) { /* get the array from python */
2009-07-26 18:18:14 +00:00
buffer_is_compat = FALSE ;
2009-06-30 12:52:16 +00:00
if ( PyObject_CheckBuffer ( seq ) ) {
Py_buffer buf ;
PyObject_GetBuffer ( seq , & buf , PyBUF_SIMPLE | PyBUF_FORMAT ) ;
2009-07-01 13:31:36 +00:00
/* check if the buffer matches */
2009-06-30 12:52:16 +00:00
buffer_is_compat = foreach_compat_buffer ( raw_type , attr_signed , buf . format ) ;
if ( buffer_is_compat ) {
ok = RNA_property_collection_raw_set ( NULL , & self - > ptr , self - > prop , attr , buf . buf , raw_type , tot ) ;
}
PyBuffer_Release ( & buf ) ;
}
/* could not use the buffer, fallback to sequence */
if ( ! buffer_is_compat ) {
array = PyMem_Malloc ( size * tot ) ;
for ( ; i < tot ; i + + ) {
item = PySequence_GetItem ( seq , i ) ;
switch ( raw_type ) {
case PROP_RAW_CHAR :
( ( char * ) array ) [ i ] = ( char ) PyLong_AsSsize_t ( item ) ;
break ;
case PROP_RAW_SHORT :
( ( short * ) array ) [ i ] = ( short ) PyLong_AsSsize_t ( item ) ;
break ;
case PROP_RAW_INT :
( ( int * ) array ) [ i ] = ( int ) PyLong_AsSsize_t ( item ) ;
break ;
case PROP_RAW_FLOAT :
( ( float * ) array ) [ i ] = ( float ) PyFloat_AsDouble ( item ) ;
break ;
case PROP_RAW_DOUBLE :
( ( double * ) array ) [ i ] = ( double ) PyFloat_AsDouble ( item ) ;
break ;
2010-01-08 13:52:38 +00:00
case PROP_RAW_UNSET :
/* should never happen */
break ;
2009-06-30 12:52:16 +00:00
}
Py_DECREF ( item ) ;
}
ok = RNA_property_collection_raw_set ( NULL , & self - > ptr , self - > prop , attr , array , raw_type , tot ) ;
}
}
else {
2009-07-26 18:18:14 +00:00
buffer_is_compat = FALSE ;
2009-06-30 12:52:16 +00:00
if ( PyObject_CheckBuffer ( seq ) ) {
Py_buffer buf ;
PyObject_GetBuffer ( seq , & buf , PyBUF_SIMPLE | PyBUF_FORMAT ) ;
/* check if the buffer matches, TODO - signed/unsigned types */
buffer_is_compat = foreach_compat_buffer ( raw_type , attr_signed , buf . format ) ;
if ( buffer_is_compat ) {
ok = RNA_property_collection_raw_get ( NULL , & self - > ptr , self - > prop , attr , buf . buf , raw_type , tot ) ;
}
PyBuffer_Release ( & buf ) ;
}
/* could not use the buffer, fallback to sequence */
if ( ! buffer_is_compat ) {
array = PyMem_Malloc ( size * tot ) ;
ok = RNA_property_collection_raw_get ( NULL , & self - > ptr , self - > prop , attr , array , raw_type , tot ) ;
if ( ! ok ) i = tot ; /* skip the loop */
for ( ; i < tot ; i + + ) {
switch ( raw_type ) {
case PROP_RAW_CHAR :
item = PyLong_FromSsize_t ( ( Py_ssize_t ) ( ( char * ) array ) [ i ] ) ;
break ;
case PROP_RAW_SHORT :
item = PyLong_FromSsize_t ( ( Py_ssize_t ) ( ( short * ) array ) [ i ] ) ;
break ;
case PROP_RAW_INT :
item = PyLong_FromSsize_t ( ( Py_ssize_t ) ( ( int * ) array ) [ i ] ) ;
break ;
case PROP_RAW_FLOAT :
item = PyFloat_FromDouble ( ( double ) ( ( float * ) array ) [ i ] ) ;
break ;
case PROP_RAW_DOUBLE :
item = PyFloat_FromDouble ( ( double ) ( ( double * ) array ) [ i ] ) ;
break ;
2010-01-08 13:52:38 +00:00
case PROP_RAW_UNSET :
/* should never happen */
break ;
2009-06-30 12:52:16 +00:00
}
PySequence_SetItem ( seq , i , item ) ;
Py_DECREF ( item ) ;
}
}
}
2009-12-08 09:40:30 +00:00
if ( array )
PyMem_Free ( array ) ;
2009-06-30 12:52:16 +00:00
if ( PyErr_Occurred ( ) ) {
/* Maybe we could make our own error */
PyErr_Print ( ) ;
PyErr_SetString ( PyExc_SystemError , " could not access the py sequence " ) ;
return NULL ;
}
if ( ! ok ) {
PyErr_SetString ( PyExc_SystemError , " internal error setting the array " ) ;
return NULL ;
}
Py_RETURN_NONE ;
}
static PyObject * pyrna_prop_foreach_get ( BPy_PropertyRNA * self , PyObject * args )
{
return foreach_getset ( self , args , 0 ) ;
}
static PyObject * pyrna_prop_foreach_set ( BPy_PropertyRNA * self , PyObject * args )
{
return foreach_getset ( self , args , 1 ) ;
}
2008-12-02 15:27:10 +00:00
/* A bit of a kludge, make a list out of a collection or array,
* then return the lists iter function , not especially fast but convenient for now */
2010-02-15 23:43:51 +00:00
PyObject * pyrna_prop_array_iter ( BPy_PropertyRNA * self )
2008-12-02 15:27:10 +00:00
{
/* Try get values from a collection */
2009-09-15 10:01:20 +00:00
PyObject * ret ;
2010-02-09 19:22:57 +00:00
PyObject * iter = NULL ;
2010-02-15 23:43:51 +00:00
int len = pyrna_prop_array_length ( self ) ;
ret = pyrna_prop_array_subscript_slice ( self , & self - > ptr , self - > prop , 0 , len , len ) ;
2008-12-02 15:27:10 +00:00
2010-02-15 23:43:51 +00:00
/* we know this is a list so no need to PyIter_Check
* otherwise it could be NULL ( unlikely ) if conversion failed */
if ( ret ) {
iter = PyObject_GetIter ( ret ) ;
Py_DECREF ( ret ) ;
2008-12-02 15:27:10 +00:00
}
2010-02-15 23:43:51 +00:00
return iter ;
}
PyObject * pyrna_prop_collection_iter ( BPy_PropertyRNA * self )
{
/* Try get values from a collection */
PyObject * ret ;
PyObject * iter = NULL ;
ret = pyrna_prop_values ( self ) ;
2009-09-15 10:01:20 +00:00
2010-02-09 19:22:57 +00:00
/* we know this is a list so no need to PyIter_Check
* otherwise it could be NULL ( unlikely ) if conversion failed */
if ( ret ) {
iter = PyObject_GetIter ( ret ) ;
Py_DECREF ( ret ) ;
}
2009-09-15 10:01:20 +00:00
return iter ;
2008-12-02 15:27:10 +00:00
}
2009-03-11 17:28:37 +00:00
static struct PyMethodDef pyrna_struct_methods [ ] = {
2009-07-08 09:23:49 +00:00
2009-11-16 20:16:45 +00:00
/* only for PointerRNA's with ID'props */
{ " keys " , ( PyCFunction ) pyrna_struct_keys , METH_NOARGS , NULL } ,
{ " values " , ( PyCFunction ) pyrna_struct_values , METH_NOARGS , NULL } ,
{ " items " , ( PyCFunction ) pyrna_struct_items , METH_NOARGS , NULL } ,
2009-11-23 23:17:23 +00:00
{ " get " , ( PyCFunction ) pyrna_struct_get , METH_VARARGS , NULL } ,
2009-07-08 09:23:49 +00:00
/* maybe this become and ID function */
{ " keyframe_insert " , ( PyCFunction ) pyrna_struct_keyframe_insert , METH_VARARGS , NULL } ,
2009-11-04 15:16:41 +00:00
{ " driver_add " , ( PyCFunction ) pyrna_struct_driver_add , METH_VARARGS , NULL } ,
Key Configuration
Keymaps are now saveable and configurable from the user preferences, note
that editing one item in a keymap means the whole keymap is now defined by
the user and will not be updated by Blender, an option for syncing might be
added later. The outliner interface is still there, but I will probably
remove it.
There's actually 3 levels now:
* Default builtin key configuration.
* Key configuration loaded from .py file, for configs like Blender 2.4x
or other 3D applications.
* Keymaps edited by the user and saved in .B.blend. These can be saved
to .py files as well to make creating distributable configurations
easier.
Also, user preferences sections were reorganized a bit, now there is:
Interface, Editing, Input, Files and System.
Implementation notes:
* wmKeyConfig was added which represents a key configuration containing
keymaps.
* wmKeymapItem was renamed to wmKeyMapItem for consistency with wmKeyMap.
* Modal maps are not wrapped yet.
* User preferences DNA file reading did not support newdataadr() yet,
added this now for reading keymaps.
* Key configuration related settings are now RNA wrapped.
* is_property_set and is_property_hidden python methods were added.
2009-10-08 18:40:03 +00:00
{ " is_property_set " , ( PyCFunction ) pyrna_struct_is_property_set , METH_VARARGS , NULL } ,
{ " is_property_hidden " , ( PyCFunction ) pyrna_struct_is_property_hidden , METH_VARARGS , NULL } ,
2009-11-17 20:46:59 +00:00
{ " path_resolve " , ( PyCFunction ) pyrna_struct_path_resolve , METH_O , NULL } ,
2009-11-23 23:17:23 +00:00
{ " path_to_id " , ( PyCFunction ) pyrna_struct_path_to_id , METH_VARARGS , NULL } ,
2010-01-17 20:06:34 +00:00
{ " recast_type " , ( PyCFunction ) pyrna_struct_recast_type , METH_NOARGS , NULL } ,
2009-06-30 12:52:16 +00:00
{ " __dir__ " , ( PyCFunction ) pyrna_struct_dir , METH_NOARGS , NULL } ,
2008-12-29 12:04:25 +00:00
{ NULL , NULL , 0 , NULL }
2009-03-11 17:28:37 +00:00
} ;
2008-11-29 13:36:08 +00:00
static struct PyMethodDef pyrna_prop_methods [ ] = {
2010-02-15 23:43:51 +00:00
{ " path_to_id " , ( PyCFunction ) pyrna_prop_path_to_id , METH_NOARGS , NULL } ,
{ " __dir__ " , ( PyCFunction ) pyrna_prop_dir , METH_NOARGS , NULL } ,
{ NULL , NULL , 0 , NULL }
} ;
static struct PyMethodDef pyrna_prop_array_methods [ ] = {
{ " foreach_get " , ( PyCFunction ) pyrna_prop_foreach_get , METH_VARARGS , NULL } ,
{ " foreach_set " , ( PyCFunction ) pyrna_prop_foreach_set , METH_VARARGS , NULL } ,
{ NULL , NULL , 0 , NULL }
} ;
static struct PyMethodDef pyrna_prop_collection_methods [ ] = {
2010-02-16 19:27:38 +00:00
{ " foreach_get " , ( PyCFunction ) pyrna_prop_foreach_get , METH_VARARGS , NULL } ,
{ " foreach_set " , ( PyCFunction ) pyrna_prop_foreach_set , METH_VARARGS , NULL } ,
2009-06-30 12:52:16 +00:00
{ " keys " , ( PyCFunction ) pyrna_prop_keys , METH_NOARGS , NULL } ,
{ " items " , ( PyCFunction ) pyrna_prop_items , METH_NOARGS , NULL } ,
{ " values " , ( PyCFunction ) pyrna_prop_values , METH_NOARGS , NULL } ,
2009-07-09 08:06:26 +00:00
{ " get " , ( PyCFunction ) pyrna_prop_get , METH_VARARGS , NULL } ,
2009-06-30 12:52:16 +00:00
2009-11-11 16:28:53 +00:00
/* moved into a getset */
{ " add " , ( PyCFunction ) pyrna_prop_add , METH_NOARGS , NULL } ,
{ " remove " , ( PyCFunction ) pyrna_prop_remove , METH_O , NULL } ,
2008-11-29 13:36:08 +00:00
{ NULL , NULL , 0 , NULL }
} ;
2008-12-01 16:59:18 +00:00
/* only needed for subtyping, so a new class gets a valid BPy_StructRNA
* todo - also accept useful args */
static PyObject * pyrna_struct_new ( PyTypeObject * type , PyObject * args , PyObject * kwds ) {
BPy_StructRNA * base = NULL ;
if ( ! PyArg_ParseTuple ( args , " O!:Base BPy_StructRNA " , & pyrna_struct_Type , & base ) )
return NULL ;
if ( type = = & pyrna_struct_Type ) {
return pyrna_struct_CreatePyObject ( & base - > ptr ) ;
} else {
BPy_StructRNA * ret = ( BPy_StructRNA * ) type - > tp_alloc ( type , 0 ) ;
ret - > ptr = base - > ptr ;
return ( PyObject * ) ret ;
}
}
/* only needed for subtyping, so a new class gets a valid BPy_StructRNA
* todo - also accept useful args */
static PyObject * pyrna_prop_new ( PyTypeObject * type , PyObject * args , PyObject * kwds ) {
BPy_PropertyRNA * base = NULL ;
if ( ! PyArg_ParseTuple ( args , " O!:Base BPy_PropertyRNA " , & pyrna_prop_Type , & base ) )
return NULL ;
2010-02-15 23:43:51 +00:00
if ( ELEM3 ( type , & pyrna_prop_Type , & pyrna_prop_array_Type , & pyrna_prop_collection_Type ) ) {
2008-12-01 16:59:18 +00:00
return pyrna_prop_CreatePyObject ( & base - > ptr , base - > prop ) ;
} else {
BPy_PropertyRNA * ret = ( BPy_PropertyRNA * ) type - > tp_alloc ( type , 0 ) ;
ret - > ptr = base - > ptr ;
ret - > prop = base - > prop ;
return ( PyObject * ) ret ;
}
}
2010-01-24 10:51:59 +00:00
PyObject * pyrna_param_to_py ( PointerRNA * ptr , ParameterList * parms , PropertyRNA * prop , void * data )
2009-04-07 00:49:39 +00:00
{
PyObject * ret ;
2009-04-19 13:37:59 +00:00
int type = RNA_property_type ( prop ) ;
2010-01-08 13:52:38 +00:00
int flag = RNA_property_flag ( prop ) ;
2009-04-07 00:49:39 +00:00
int a ;
2009-09-15 10:01:20 +00:00
if ( RNA_property_array_check ( ptr , prop ) ) {
2010-01-24 10:51:59 +00:00
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 ) ;
2009-09-15 10:01:20 +00:00
2009-04-07 00:49:39 +00:00
/* resolve the array from a new pytype */
2009-09-06 15:13:57 +00:00
/* kazanbas: TODO make multidim sequences here */
2009-04-07 00:49:39 +00:00
switch ( type ) {
case PROP_BOOLEAN :
2010-01-04 13:29:55 +00:00
ret = PyTuple_New ( len ) ;
2009-04-07 00:49:39 +00:00
for ( a = 0 ; a < len ; a + + )
PyTuple_SET_ITEM ( ret , a , PyBool_FromLong ( ( ( int * ) data ) [ a ] ) ) ;
break ;
case PROP_INT :
2010-01-04 13:29:55 +00:00
ret = PyTuple_New ( len ) ;
2009-04-07 00:49:39 +00:00
for ( a = 0 ; a < len ; a + + )
PyTuple_SET_ITEM ( ret , a , PyLong_FromSsize_t ( ( Py_ssize_t ) ( ( int * ) data ) [ a ] ) ) ;
break ;
case PROP_FLOAT :
2010-01-04 13:29:55 +00:00
switch ( RNA_property_subtype ( prop ) ) {
case PROP_ALL_VECTOR_SUBTYPES :
ret = newVectorObject ( data , len , Py_NEW , NULL ) ;
break ;
case PROP_MATRIX :
if ( len = = 16 ) {
ret = newMatrixObject ( data , 4 , 4 , Py_NEW , NULL ) ;
break ;
}
else if ( len = = 9 ) {
ret = newMatrixObject ( data , 3 , 3 , Py_NEW , NULL ) ;
break ;
}
/* pass through */
default :
ret = PyTuple_New ( len ) ;
for ( a = 0 ; a < len ; a + + )
PyTuple_SET_ITEM ( ret , a , PyFloat_FromDouble ( ( ( float * ) data ) [ a ] ) ) ;
}
2009-04-07 00:49:39 +00:00
break ;
default :
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_TypeError , " RNA Error: unknown array type \" %d \" (pyrna_param_to_py) " , type ) ;
2009-04-07 00:49:39 +00:00
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 :
{
2010-01-08 13:52:38 +00:00
if ( flag & PROP_THICK_WRAP )
ret = PyUnicode_FromString ( ( char * ) data ) ;
else
ret = PyUnicode_FromString ( * ( char * * ) data ) ;
2009-04-07 00:49:39 +00:00
break ;
}
case PROP_ENUM :
{
2009-12-07 00:16:57 +00:00
ret = pyrna_enum_to_py ( ptr , prop , * ( int * ) data ) ;
2009-04-07 00:49:39 +00:00
break ;
}
case PROP_POINTER :
{
PointerRNA newptr ;
2009-06-07 13:09:18 +00:00
StructRNA * type = RNA_property_pointer_type ( ptr , prop ) ;
2009-04-07 00:49:39 +00:00
2009-06-16 00:52:21 +00:00
if ( flag & PROP_RNAPTR ) {
2009-04-07 00:49:39 +00:00
/* in this case we get the full ptr */
newptr = * ( PointerRNA * ) data ;
}
else {
2009-07-28 01:06:56 +00:00
if ( RNA_struct_is_ID ( type ) ) {
RNA_id_pointer_create ( * ( void * * ) data , & newptr ) ;
} else {
2009-11-16 09:20:21 +00:00
/* note: this is taken from the function's ID pointer
* and will break if a function returns a pointer from
* another ID block , watch this ! - it should at least be
* easy to debug since they are all ID ' s */
RNA_pointer_create ( ptr - > id . data , type , * ( void * * ) data , & newptr ) ;
2009-07-28 01:06:56 +00:00
}
2009-04-07 00:49:39 +00:00
}
if ( newptr . data ) {
ret = pyrna_struct_CreatePyObject ( & newptr ) ;
} else {
ret = Py_None ;
Py_INCREF ( ret ) ;
}
break ;
}
case PROP_COLLECTION :
2009-06-27 01:10:39 +00:00
{
ListBase * lb = ( ListBase * ) data ;
CollectionPointerLink * link ;
PyObject * linkptr ;
ret = PyList_New ( 0 ) ;
for ( link = lb - > first ; link ; link = link - > next ) {
linkptr = pyrna_struct_CreatePyObject ( & link - > ptr ) ;
PyList_Append ( ret , linkptr ) ;
Py_DECREF ( linkptr ) ;
}
2009-04-07 00:49:39 +00:00
break ;
2009-06-27 01:10:39 +00:00
}
2009-04-07 00:49:39 +00:00
default :
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_TypeError , " RNA Error: unknown type \" %d \" (pyrna_param_to_py) " , type ) ;
2009-04-07 00:49:39 +00:00
ret = NULL ;
break ;
}
}
return ret ;
}
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_func_call ( PyObject * self , PyObject * args , PyObject * kw )
2009-04-09 13:20:48 +00:00
{
2009-11-11 16:28:53 +00:00
/* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here */
PointerRNA * self_ptr = & ( ( ( BPy_DummyPointerRNA * ) PyTuple_GET_ITEM ( self , 0 ) ) - > ptr ) ;
2010-02-12 21:14:01 +00:00
FunctionRNA * self_func = PyCapsule_GetPointer ( PyTuple_GET_ITEM ( self , 1 ) , NULL ) ;
2009-04-09 13:20:48 +00:00
2009-04-07 00:49:39 +00:00
PointerRNA funcptr ;
2009-07-17 02:31:28 +00:00
ParameterList parms ;
2009-04-07 00:49:39 +00:00
ParameterIterator iter ;
2010-01-02 10:42:38 +00:00
PropertyRNA * parm ;
2009-04-07 00:49:39 +00:00
PyObject * ret , * item ;
2010-01-02 10:42:38 +00:00
int i , args_len , parms_len , ret_len , flag , err = 0 , kw_tot = 0 , kw_arg ;
2009-07-17 02:31:28 +00:00
const char * parm_id ;
2010-01-02 10:42:38 +00:00
PropertyRNA * pret_single = NULL ;
void * retdata_single = NULL ;
2009-04-07 00:49:39 +00:00
2009-07-17 12:26:40 +00:00
/* Should never happen but it does in rare cases */
if ( self_ptr = = NULL ) {
PyErr_SetString ( PyExc_RuntimeError , " rna functions internal rna pointer is NULL, this is a bug. aborting " ) ;
return NULL ;
}
if ( self_func = = NULL ) {
2009-07-23 13:48:15 +00:00
PyErr_Format ( PyExc_RuntimeError , " %.200s.<unknown>(): rna function internal function is NULL, this is a bug. aborting " , RNA_struct_identifier ( self_ptr - > type ) ) ;
2009-07-17 12:26:40 +00:00
return NULL ;
}
2009-11-16 09:20:21 +00:00
/* include the ID pointer for pyrna_param_to_py() so we can include the
* ID pointer on return values , this only works when returned values have
* the same ID as the functions . */
RNA_pointer_create ( self_ptr - > id . data , & RNA_Function , self_func , & funcptr ) ;
2009-04-07 00:49:39 +00:00
2009-07-17 02:31:28 +00:00
args_len = PyTuple_GET_SIZE ( args ) ;
2009-04-07 00:49:39 +00:00
2009-07-17 02:31:28 +00:00
RNA_parameter_list_create ( & parms , self_ptr , self_func ) ;
RNA_parameter_list_begin ( & parms , & iter ) ;
2010-01-02 10:42:38 +00:00
parms_len = RNA_parameter_list_size ( & parms ) ;
ret_len = 0 ;
2009-07-17 02:31:28 +00:00
if ( args_len + ( kw ? PyDict_Size ( kw ) : 0 ) > parms_len ) {
2010-01-02 19:01:19 +00:00
RNA_parameter_list_end ( & iter ) ;
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s.%.200s(): takes at most %d arguments, got %d " , RNA_struct_identifier ( self_ptr - > type ) , RNA_function_identifier ( self_func ) , parms_len , args_len ) ;
err = - 1 ;
}
2009-04-07 00:49:39 +00:00
/* parse function parameters */
2009-07-17 02:31:28 +00:00
for ( i = 0 ; iter . valid & & err = = 0 ; RNA_parameter_list_next ( & iter ) ) {
2009-04-07 00:49:39 +00:00
parm = iter . parm ;
2010-01-02 10:42:38 +00:00
flag = RNA_property_flag ( parm ) ;
/* only useful for single argument returns, we'll need another list loop for multiple */
2010-01-24 10:51:59 +00:00
if ( flag & PROP_OUTPUT ) {
2010-01-02 10:42:38 +00:00
ret_len + + ;
if ( pret_single = = NULL ) {
pret_single = parm ;
retdata_single = iter . data ;
}
2009-04-07 00:49:39 +00:00
continue ;
}
2009-07-17 02:31:28 +00:00
parm_id = RNA_property_identifier ( parm ) ;
2009-04-07 00:49:39 +00:00
item = NULL ;
2009-07-17 02:31:28 +00:00
if ( ( i < args_len ) & & ( flag & PROP_REQUIRED ) ) {
2009-04-07 00:49:39 +00:00
item = PyTuple_GET_ITEM ( args , i ) ;
2009-04-11 01:45:05 +00:00
i + + ;
2009-07-23 13:48:15 +00:00
2009-07-26 18:18:14 +00:00
kw_arg = FALSE ;
2009-04-11 01:45:05 +00:00
}
2009-07-17 02:31:28 +00:00
else if ( kw ! = NULL ) {
item = PyDict_GetItemString ( kw , parm_id ) ; /* borrow ref */
if ( item )
kw_tot + + ; /* make sure invalid keywords are not given */
2009-07-23 13:48:15 +00:00
2009-07-26 18:18:14 +00:00
kw_arg = TRUE ;
2009-07-17 02:31:28 +00:00
}
2009-04-07 00:49:39 +00:00
if ( item = = NULL ) {
2009-04-11 01:45:05 +00:00
if ( flag & PROP_REQUIRED ) {
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_TypeError , " %.200s.%.200s(): required parameter \" %.200s \" not specified " , RNA_struct_identifier ( self_ptr - > type ) , RNA_function_identifier ( self_func ) , parm_id ) ;
2009-04-11 01:45:05 +00:00
err = - 1 ;
break ;
}
2009-07-17 02:31:28 +00:00
else /* PyDict_GetItemString wont raise an error */
2009-04-11 01:45:05 +00:00
continue ;
2009-04-07 00:49:39 +00:00
}
2010-01-24 10:51:59 +00:00
err = pyrna_py_to_prop ( & funcptr , parm , & parms , iter . data , item , " " ) ;
2009-07-23 13:48:15 +00:00
if ( err ! = 0 ) {
/* the error generated isnt that useful, so generate it again with a useful prefix
* could also write a function to prepend to error messages */
char error_prefix [ 512 ] ;
PyErr_Clear ( ) ; /* re-raise */
2009-07-26 18:18:14 +00:00
if ( kw_arg = = TRUE )
2009-07-23 13:48:15 +00:00
snprintf ( error_prefix , sizeof ( error_prefix ) , " %s.%s(): error with keyword argument \" %s \" - " , RNA_struct_identifier ( self_ptr - > type ) , RNA_function_identifier ( self_func ) , parm_id ) ;
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 ) ;
2010-01-24 10:51:59 +00:00
pyrna_py_to_prop ( & funcptr , parm , & parms , iter . data , item , error_prefix ) ;
2009-04-07 00:49:39 +00:00
break ;
2009-07-23 13:48:15 +00:00
}
2009-04-07 00:49:39 +00:00
}
2010-01-02 19:01:19 +00:00
RNA_parameter_list_end ( & iter ) ;
2009-04-07 00:49:39 +00:00
2009-07-17 02:31:28 +00:00
/* Check if we gave args that dont exist in the function
* printing the error is slow but it should only happen when developing .
2009-09-17 00:14:47 +00:00
* the if below is quick , checking if it passed less keyword args then we gave .
* ( Dont overwrite the error if we have one , otherwise can skip important messages and confuse with args )
*/
if ( err = = 0 & & kw & & ( PyDict_Size ( kw ) > kw_tot ) ) {
2009-07-17 02:31:28 +00:00
PyObject * key , * value ;
Py_ssize_t pos = 0 ;
DynStr * bad_args = BLI_dynstr_new ( ) ;
DynStr * good_args = BLI_dynstr_new ( ) ;
char * arg_name , * bad_args_str , * good_args_str ;
2009-07-26 18:18:14 +00:00
int found = FALSE , first = TRUE ;
2009-07-17 02:31:28 +00:00
while ( PyDict_Next ( kw , & pos , & key , & value ) ) {
arg_name = _PyUnicode_AsString ( key ) ;
2009-07-26 18:18:14 +00:00
found = FALSE ;
2009-07-17 02:31:28 +00:00
if ( arg_name = = NULL ) { /* unlikely the argname is not a string but ignore if it is*/
PyErr_Clear ( ) ;
}
else {
/* Search for arg_name */
RNA_parameter_list_begin ( & parms , & iter ) ;
for ( ; iter . valid ; RNA_parameter_list_next ( & iter ) ) {
parm = iter . parm ;
if ( strcmp ( arg_name , RNA_property_identifier ( parm ) ) = = 0 ) {
2009-07-26 18:18:14 +00:00
found = TRUE ;
2009-07-17 02:31:28 +00:00
break ;
}
}
RNA_parameter_list_end ( & iter ) ;
2009-07-26 18:18:14 +00:00
if ( found = = FALSE ) {
2009-07-17 02:31:28 +00:00
BLI_dynstr_appendf ( bad_args , first ? " %s " : " , %s " , arg_name ) ;
2009-07-26 18:18:14 +00:00
first = FALSE ;
2009-07-17 02:31:28 +00:00
}
}
}
/* list good args */
2009-07-26 18:18:14 +00:00
first = TRUE ;
2009-07-17 02:31:28 +00:00
RNA_parameter_list_begin ( & parms , & iter ) ;
for ( ; iter . valid ; RNA_parameter_list_next ( & iter ) ) {
parm = iter . parm ;
2010-01-24 10:51:59 +00:00
if ( RNA_property_flag ( parm ) & PROP_OUTPUT )
2009-12-10 11:20:43 +00:00
continue ;
2009-07-17 02:31:28 +00:00
BLI_dynstr_appendf ( good_args , first ? " %s " : " , %s " , RNA_property_identifier ( parm ) ) ;
2009-07-26 18:18:14 +00:00
first = FALSE ;
2009-07-17 02:31:28 +00:00
}
RNA_parameter_list_end ( & iter ) ;
bad_args_str = BLI_dynstr_get_cstring ( bad_args ) ;
good_args_str = BLI_dynstr_get_cstring ( good_args ) ;
PyErr_Format ( PyExc_TypeError , " %.200s.%.200s(): was called with invalid keyword arguments(s) (%s), expected (%s) " , RNA_struct_identifier ( self_ptr - > type ) , RNA_function_identifier ( self_func ) , bad_args_str , good_args_str ) ;
BLI_dynstr_free ( bad_args ) ;
BLI_dynstr_free ( good_args ) ;
MEM_freeN ( bad_args_str ) ;
MEM_freeN ( good_args_str ) ;
err = - 1 ;
}
2009-04-07 00:49:39 +00:00
ret = NULL ;
if ( err = = 0 ) {
/* call function */
2009-06-18 19:48:55 +00:00
ReportList reports ;
bContext * C = BPy_GetContext ( ) ;
BKE_reports_init ( & reports , RPT_STORE ) ;
2009-07-17 02:31:28 +00:00
RNA_function_call ( C , & reports , self_ptr , self_func , & parms ) ;
2009-06-18 19:48:55 +00:00
err = ( BPy_reports_to_error ( & reports ) ) ? - 1 : 0 ;
BKE_reports_clear ( & reports ) ;
2009-04-07 00:49:39 +00:00
/* return value */
2009-07-17 02:31:28 +00:00
if ( err = = 0 ) {
2010-01-02 10:42:38 +00:00
if ( ret_len > 0 ) {
if ( ret_len > 1 ) {
ret = PyTuple_New ( ret_len ) ;
i = 0 ; /* arg index */
RNA_parameter_list_begin ( & parms , & iter ) ;
for ( ; iter . valid ; RNA_parameter_list_next ( & iter ) ) {
parm = iter . parm ;
flag = RNA_property_flag ( parm ) ;
2010-01-24 10:51:59 +00:00
if ( flag & PROP_OUTPUT )
PyTuple_SET_ITEM ( ret , i + + , pyrna_param_to_py ( & funcptr , & parms , parm , iter . data ) ) ;
2010-01-02 10:42:38 +00:00
}
RNA_parameter_list_end ( & iter ) ;
}
else
2010-01-24 10:51:59 +00:00
ret = pyrna_param_to_py ( & funcptr , & parms , pret_single , retdata_single ) ;
2009-07-17 02:31:28 +00:00
/* possible there is an error in conversion */
if ( ret = = NULL )
err = - 1 ;
}
}
2009-04-07 00:49:39 +00:00
}
/* cleanup */
RNA_parameter_list_end ( & iter ) ;
2009-07-17 02:31:28 +00:00
RNA_parameter_list_free ( & parms ) ;
2009-04-07 00:49:39 +00:00
if ( ret )
return ret ;
if ( err = = - 1 )
return NULL ;
Py_RETURN_NONE ;
}
2008-11-29 13:36:08 +00:00
/*-----------------------BPy_StructRNA method def------------------------------*/
PyTypeObject pyrna_struct_Type = {
2009-01-29 09:38:52 +00:00
PyVarObject_HEAD_INIT ( NULL , 0 )
2008-11-29 13:36:08 +00:00
" StructRNA " , /* tp_name */
sizeof ( BPy_StructRNA ) , /* tp_basicsize */
0 , /* tp_itemsize */
/* methods */
2008-12-29 03:24:13 +00:00
( destructor ) pyrna_struct_dealloc , /* tp_dealloc */
2008-11-29 13:36:08 +00:00
NULL , /* printfunc tp_print; */
2008-12-01 16:59:18 +00:00
NULL , /* getattrfunc tp_getattr; */
NULL , /* setattrfunc tp_setattr; */
2009-02-26 05:50:19 +00:00
NULL , /* tp_compare */ /* DEPRECATED in python 3.0! */
2008-11-29 13:36:08 +00:00
( reprfunc ) pyrna_struct_repr , /* tp_repr */
/* Method suites for standard classes */
NULL , /* PyNumberMethods *tp_as_number; */
2009-11-16 19:03:40 +00:00
& pyrna_struct_as_sequence , /* PySequenceMethods *tp_as_sequence; */
& pyrna_struct_as_mapping , /* PyMappingMethods *tp_as_mapping; */
2008-11-29 13:36:08 +00:00
/* More standard operations (here for binary compatibility) */
2008-12-02 14:36:35 +00:00
( hashfunc ) pyrna_struct_hash , /* hashfunc tp_hash; */
2008-12-01 16:59:18 +00:00
NULL , /* ternaryfunc tp_call; */
2008-11-29 13:36:08 +00:00
NULL , /* reprfunc tp_str; */
2008-12-01 16:59:18 +00:00
( getattrofunc ) pyrna_struct_getattro , /* getattrofunc tp_getattro; */
( setattrofunc ) pyrna_struct_setattro , /* setattrofunc tp_setattro; */
2008-11-29 13:36:08 +00:00
/* Functions to access object as input/output buffer */
NULL , /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
2008-12-01 16:59:18 +00:00
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* long tp_flags; */
2008-11-29 13:36:08 +00:00
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 ***/
2009-01-29 09:38:52 +00:00
( richcmpfunc ) pyrna_struct_richcmp , /* richcmpfunc tp_richcompare; */
2008-11-29 13:36:08 +00:00
/*** weak reference enabler ***/
0 , /* long tp_weaklistoffset; */
/*** Added in release 2.2 ***/
/* Iterators */
NULL , /* getiterfunc tp_iter; */
NULL , /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
2009-03-11 17:28:37 +00:00
pyrna_struct_methods , /* struct PyMethodDef *tp_methods; */
2008-11-29 13:36:08 +00:00
NULL , /* struct PyMemberDef *tp_members; */
2009-12-13 10:46:34 +00:00
pyrna_struct_getseters , /* struct PyGetSetDef *tp_getset; */
2008-11-29 13:36:08 +00:00
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; */
2008-12-01 16:59:18 +00:00
pyrna_struct_new , /* newfunc tp_new; */
2008-11-29 13:36:08 +00:00
/* 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
} ;
/*-----------------------BPy_PropertyRNA method def------------------------------*/
PyTypeObject pyrna_prop_Type = {
2009-01-29 09:38:52 +00:00
PyVarObject_HEAD_INIT ( NULL , 0 )
2008-11-29 13:36:08 +00:00
" PropertyRNA " , /* tp_name */
sizeof ( BPy_PropertyRNA ) , /* tp_basicsize */
0 , /* tp_itemsize */
/* methods */
NULL , /* tp_dealloc */
NULL , /* printfunc tp_print; */
2008-11-30 14:00:14 +00:00
NULL , /* getattrfunc tp_getattr; */
2008-11-29 13:36:08 +00:00
NULL , /* setattrfunc tp_setattr; */
2009-02-26 05:50:19 +00:00
NULL , /* tp_compare */ /* DEPRECATED in python 3.0! */
2008-11-29 13:36:08 +00:00
( reprfunc ) pyrna_prop_repr , /* tp_repr */
/* Method suites for standard classes */
NULL , /* PyNumberMethods *tp_as_number; */
2010-02-15 23:43:51 +00:00
NULL , /* PySequenceMethods *tp_as_sequence; */
NULL , /* PyMappingMethods *tp_as_mapping; */
2008-11-29 13:36:08 +00:00
/* More standard operations (here for binary compatibility) */
NULL , /* hashfunc tp_hash; */
NULL , /* ternaryfunc tp_call; */
NULL , /* reprfunc tp_str; */
2009-11-03 16:07:29 +00:00
/* will only use these if this is a subtype of a py class */
2010-02-15 23:43:51 +00:00
NULL , /* getattrofunc tp_getattro; */
NULL , /* setattrofunc tp_setattro; */
2008-11-29 13:36:08 +00:00
/* Functions to access object as input/output buffer */
NULL , /* PyBufferProcs *tp_as_buffer; */
/*** Flags to define presence of optional/expanded features ***/
2008-12-01 16:59:18 +00:00
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* long tp_flags; */
2008-11-29 13:36:08 +00:00
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 ***/
2009-01-29 09:38:52 +00:00
( richcmpfunc ) pyrna_prop_richcmp , /* richcmpfunc tp_richcompare; */
2008-11-29 13:36:08 +00:00
/*** weak reference enabler ***/
0 , /* long tp_weaklistoffset; */
/*** Added in release 2.2 ***/
/* Iterators */
2010-02-15 23:43:51 +00:00
NULL , /* getiterfunc tp_iter; */
2008-11-29 13:36:08 +00:00
NULL , /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
pyrna_prop_methods , /* struct PyMethodDef *tp_methods; */
NULL , /* struct PyMemberDef *tp_members; */
2009-11-13 16:08:03 +00:00
NULL /*pyrna_prop_getseters*/ , /* struct PyGetSetDef *tp_getset; */
2008-11-29 13:36:08 +00:00
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; */
2008-12-01 16:59:18 +00:00
pyrna_prop_new , /* newfunc tp_new; */
2008-11-29 13:36:08 +00:00
/* 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
} ;
2010-02-15 23:43:51 +00:00
PyTypeObject pyrna_prop_array_Type = {
PyVarObject_HEAD_INIT ( NULL , 0 )
" PropertyArrayRNA " , /* tp_name */
sizeof ( BPy_PropertyRNA ) , /* tp_basicsize */
0 , /* tp_itemsize */
/* methods */
NULL , /* tp_dealloc */
NULL , /* printfunc tp_print; */
NULL , /* getattrfunc tp_getattr; */
NULL , /* setattrfunc tp_setattr; */
NULL , /* tp_compare */ /* DEPRECATED in python 3.0! */
NULL , /* subclassed */ /* tp_repr */
/* Method suites for standard classes */
NULL , /* PyNumberMethods *tp_as_number; */
& pyrna_prop_array_as_sequence , /* PySequenceMethods *tp_as_sequence; */
& pyrna_prop_array_as_mapping , /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
NULL , /* hashfunc tp_hash; */
NULL , /* ternaryfunc tp_call; */
NULL , /* reprfunc tp_str; */
/* will only use these if this is a subtype of a py class */
( getattrofunc ) pyrna_prop_array_getattro , /* getattrofunc tp_getattro; */
NULL , /* 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 ***/
NULL , /* subclassed */ /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0 , /* long tp_weaklistoffset; */
/*** Added in release 2.2 ***/
/* Iterators */
( getiterfunc ) pyrna_prop_array_iter , /* getiterfunc tp_iter; */
NULL , /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
pyrna_prop_array_methods , /* struct PyMethodDef *tp_methods; */
NULL , /* struct PyMemberDef *tp_members; */
NULL /*pyrna_prop_getseters*/ , /* struct PyGetSetDef *tp_getset; */
& pyrna_prop_Type , /* 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; */
NULL , /* 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
} ;
PyTypeObject pyrna_prop_collection_Type = {
PyVarObject_HEAD_INIT ( NULL , 0 )
" PropertyCollectionRNA " , /* tp_name */
sizeof ( BPy_PropertyRNA ) , /* tp_basicsize */
0 , /* tp_itemsize */
/* methods */
NULL , /* tp_dealloc */
NULL , /* printfunc tp_print; */
NULL , /* getattrfunc tp_getattr; */
NULL , /* setattrfunc tp_setattr; */
NULL , /* tp_compare */ /* DEPRECATED in python 3.0! */
NULL , /* subclassed */ /* tp_repr */
/* Method suites for standard classes */
NULL , /* PyNumberMethods *tp_as_number; */
& pyrna_prop_collection_as_sequence , /* PySequenceMethods *tp_as_sequence; */
& pyrna_prop_collection_as_mapping , /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
NULL , /* hashfunc tp_hash; */
NULL , /* ternaryfunc tp_call; */
NULL , /* reprfunc tp_str; */
/* will only use these if this is a subtype of a py class */
( getattrofunc ) pyrna_prop_collection_getattro , /* getattrofunc tp_getattro; */
( setattrofunc ) pyrna_prop_collection_setattro , /* 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 ***/
NULL , /* subclassed */ /* richcmpfunc tp_richcompare; */
/*** weak reference enabler ***/
0 , /* long tp_weaklistoffset; */
/*** Added in release 2.2 ***/
/* Iterators */
( getiterfunc ) pyrna_prop_collection_iter , /* getiterfunc tp_iter; */
NULL , /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
pyrna_prop_collection_methods , /* struct PyMethodDef *tp_methods; */
NULL , /* struct PyMemberDef *tp_members; */
NULL /*pyrna_prop_getseters*/ , /* struct PyGetSetDef *tp_getset; */
& pyrna_prop_Type , /* 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; */
NULL , /* 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
} ;
2009-10-14 14:44:05 +00:00
static struct PyMethodDef pyrna_struct_subtype_methods [ ] = {
{ " BoolProperty " , ( PyCFunction ) BPy_BoolProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
2010-02-01 10:51:34 +00:00
{ " BoolVectorProperty " , ( PyCFunction ) BPy_BoolVectorProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
2009-10-14 14:44:05 +00:00
{ " IntProperty " , ( PyCFunction ) BPy_IntProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
2010-02-01 10:51:34 +00:00
{ " IntVectorProperty " , ( PyCFunction ) BPy_IntVectorProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
2009-10-14 14:44:05 +00:00
{ " FloatProperty " , ( PyCFunction ) BPy_FloatProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
2010-01-19 00:59:36 +00:00
{ " FloatVectorProperty " , ( PyCFunction ) BPy_FloatVectorProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
2009-10-14 14:44:05 +00:00
{ " StringProperty " , ( PyCFunction ) BPy_StringProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
{ " EnumProperty " , ( PyCFunction ) BPy_EnumProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
{ " PointerProperty " , ( PyCFunction ) BPy_PointerProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
{ " CollectionProperty " , ( PyCFunction ) BPy_CollectionProperty , METH_VARARGS | METH_KEYWORDS , " " } ,
// {"__get_rna", (PyCFunction)BPy_GetStructRNA, METH_NOARGS, ""},
{ NULL , NULL , 0 , NULL }
} ;
2009-04-19 13:37:59 +00:00
static void pyrna_subtype_set_rna ( PyObject * newclass , StructRNA * srna )
{
2009-08-16 12:29:46 +00:00
PointerRNA ptr ;
2009-04-19 13:37:59 +00:00
PyObject * item ;
2009-05-26 06:29:15 +00:00
Py_INCREF ( newclass ) ;
2009-08-15 09:53:38 +00:00
2009-05-26 06:29:15 +00:00
if ( RNA_struct_py_type_get ( srna ) )
2009-05-28 02:03:48 +00:00
PyObSpit ( " RNA WAS SET - " , RNA_struct_py_type_get ( srna ) ) ;
2009-05-28 10:31:56 +00:00
Py_XDECREF ( ( ( PyObject * ) RNA_struct_py_type_get ( srna ) ) ) ;
2009-05-26 06:29:15 +00:00
2009-04-19 13:37:59 +00:00
RNA_struct_py_type_set ( srna , ( 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 */
2009-08-15 05:05:23 +00:00
2009-08-16 12:29:46 +00:00
/* python deals with the curcular ref */
RNA_pointer_create ( NULL , & RNA_Struct , srna , & ptr ) ;
item = pyrna_struct_CreatePyObject ( & ptr ) ;
2009-08-15 05:05:23 +00:00
2010-02-12 21:14:01 +00:00
//item = PyCapsule_New(srna, NULL, NULL);
2009-10-31 13:31:23 +00:00
PyDict_SetItemString ( ( ( PyTypeObject * ) newclass ) - > tp_dict , " bl_rna " , item ) ;
2009-04-19 13:37:59 +00:00
Py_DECREF ( item ) ;
/* done with rna instance */
2009-10-14 14:44:05 +00:00
/* attach functions into the class
* so you can do . . . bpy . types . Scene . SomeFunction ( )
*/
{
PyMethodDef * ml ;
for ( ml = pyrna_struct_subtype_methods ; ml - > ml_name ; ml + + ) {
PyObject_SetAttrString ( newclass , ml - > ml_name , PyCFunction_New ( ml , newclass ) ) ;
}
}
2009-04-19 13:37:59 +00:00
}
2009-04-07 00:49:39 +00:00
2009-08-16 12:29:46 +00:00
/*
2009-08-15 05:05:23 +00:00
static StructRNA * srna_from_self ( PyObject * self ) ;
PyObject * BPy_GetStructRNA ( PyObject * self )
{
StructRNA * srna = pyrna_struct_as_srna ( self ) ;
PointerRNA ptr ;
PyObject * ret ;
RNA_pointer_create ( NULL , & RNA_Struct , srna , & ptr ) ;
ret = pyrna_struct_CreatePyObject ( & ptr ) ;
if ( ret ) {
return ret ;
}
else {
Py_RETURN_NONE ;
}
}
2009-08-16 12:29:46 +00:00
*/
2009-08-15 05:05:23 +00:00
2009-11-07 22:07:46 +00:00
static PyObject * pyrna_srna_Subtype ( StructRNA * srna ) ;
/* return a borrowed reference */
static PyObject * pyrna_srna_PyBase ( StructRNA * srna ) //, PyObject *bpy_types_dict)
{
/* Assume RNA_struct_py_type_get(srna) was already checked */
StructRNA * base ;
PyObject * py_base = NULL ;
/* get the base type */
base = RNA_struct_base ( srna ) ;
2009-11-08 01:13:19 +00:00
2009-11-07 22:07:46 +00:00
if ( base & & base ! = srna ) {
/*/printf("debug subtype %s %p\n", RNA_struct_identifier(srna), srna); */
py_base = pyrna_srna_Subtype ( base ) ; //, bpy_types_dict);
Py_DECREF ( py_base ) ; /* srna owns, this is only to pass as an arg */
}
if ( py_base = = NULL ) {
py_base = ( PyObject * ) & pyrna_struct_Type ;
}
return py_base ;
}
2009-11-08 01:13:19 +00:00
/* check if we have a native python subclass, use it when it exists
* return a borrowed reference */
static PyObject * pyrna_srna_ExternalType ( StructRNA * srna )
{
PyObject * bpy_types_dict = NULL ;
const char * idname = RNA_struct_identifier ( srna ) ;
PyObject * newclass ;
if ( bpy_types_dict = = NULL ) {
PyObject * bpy_types = PyImport_ImportModuleLevel ( " bpy_types " , NULL , NULL , NULL , 0 ) ;
if ( bpy_types = = NULL ) {
PyErr_Print ( ) ;
PyErr_Clear ( ) ;
fprintf ( stderr , " pyrna_srna_ExternalType: failed to find 'bpy_types' module \n " ) ;
return NULL ;
}
bpy_types_dict = PyModule_GetDict ( bpy_types ) ; // borrow
Py_DECREF ( bpy_types ) ; // fairly safe to assume the dict is kept
}
newclass = PyDict_GetItemString ( bpy_types_dict , idname ) ;
/* sanity check, could skip this unless in debug mode */
if ( newclass ) {
PyObject * base_compare = pyrna_srna_PyBase ( srna ) ;
2009-12-05 23:41:45 +00:00
//PyObject *slots= PyObject_GetAttrString(newclass, "__slots__"); // cant do this because it gets superclasses values!
2009-12-24 11:40:14 +00:00
//PyObject *bases= PyObject_GetAttrString(newclass, "__bases__"); // can do this but faster not to.
PyObject * bases = ( ( PyTypeObject * ) newclass ) - > tp_bases ;
2009-12-05 23:41:45 +00:00
PyObject * slots = PyDict_GetItemString ( ( ( PyTypeObject * ) newclass ) - > tp_dict , " __slots__ " ) ;
2009-11-08 01:13:19 +00:00
2009-12-05 23:41:45 +00:00
if ( slots = = NULL ) {
fprintf ( stderr , " pyrna_srna_ExternalType: expected class '%s' to have __slots__ defined \n \n See bpy_types.py \n " , idname ) ;
newclass = NULL ;
}
else if ( PyTuple_GET_SIZE ( bases ) ) {
2009-11-08 01:13:19 +00:00
PyObject * base = PyTuple_GET_ITEM ( bases , 0 ) ;
if ( base_compare ! = base ) {
2009-12-05 23:41:45 +00:00
fprintf ( stderr , " pyrna_srna_ExternalType: incorrect subclassing of SRNA '%s' \n See bpy_types.py \n " , idname ) ;
2009-11-08 01:13:19 +00:00
PyObSpit ( " Expected! " , base_compare ) ;
newclass = NULL ;
}
else {
if ( G . f & G_DEBUG )
fprintf ( stderr , " SRNA Subclassed: '%s' \n " , idname ) ;
}
}
}
return newclass ;
}
2009-11-07 22:07:46 +00:00
static PyObject * pyrna_srna_Subtype ( StructRNA * srna )
2009-03-13 07:50:07 +00:00
{
PyObject * newclass = NULL ;
2009-07-10 04:25:49 +00:00
if ( srna = = NULL ) {
2009-03-13 07:50:07 +00:00
newclass = NULL ; /* Nothing to do */
2009-07-10 04:25:49 +00:00
} else if ( ( newclass = RNA_struct_py_type_get ( srna ) ) ) {
2009-03-21 06:55:30 +00:00
Py_INCREF ( newclass ) ;
2009-11-08 01:13:19 +00:00
} else if ( ( newclass = pyrna_srna_ExternalType ( srna ) ) ) {
pyrna_subtype_set_rna ( newclass , srna ) ;
Py_INCREF ( newclass ) ;
2009-07-10 04:25:49 +00:00
} else {
2009-03-13 07:50:07 +00:00
/* subclass equivelents
- class myClass ( myBase ) :
some = ' value ' # or . . .
2009-07-10 04:25:49 +00:00
- myClass = type ( name = ' myClass ' , bases = ( myBase , ) , dict = { ' __module__ ' : ' bpy . types ' } )
2009-03-13 07:50:07 +00:00
*/
2009-07-22 19:50:21 +00:00
/* Assume RNA_struct_py_type_get(srna) was alredy checked */
2009-11-07 22:07:46 +00:00
PyObject * py_base = pyrna_srna_PyBase ( srna ) ;
2009-07-22 19:50:21 +00:00
const char * idname = RNA_struct_identifier ( srna ) ;
const char * descr = RNA_struct_ui_description ( srna ) ;
if ( ! descr ) descr = " (no docs) " ;
2009-03-13 07:50:07 +00:00
2009-08-14 12:29:55 +00:00
/* always use O not N when calling, N causes refcount errors */
2009-12-05 23:41:45 +00:00
newclass = PyObject_CallFunction ( ( PyObject * ) & PyType_Type , " s(O){sssss()} " , idname , py_base , " __module__ " , " bpy.types " , " __doc__ " , descr , " __slots__ " ) ;
2009-08-15 09:53:38 +00:00
/* newclass will now have 2 ref's, ???, probably 1 is internal since decrefing here segfaults */
/* PyObSpit("new class ref", newclass); */
2009-03-21 06:55:30 +00:00
2009-07-10 04:25:49 +00:00
if ( newclass ) {
2009-08-15 09:53:38 +00:00
/* srna owns one, and the other is owned by the caller */
2009-07-10 04:25:49 +00:00
pyrna_subtype_set_rna ( newclass , srna ) ;
2009-08-14 12:29:55 +00:00
2009-08-15 09:53:38 +00:00
Py_DECREF ( newclass ) ; /* let srna own */
2009-07-10 04:25:49 +00:00
}
else {
/* this should not happen */
PyErr_Print ( ) ;
PyErr_Clear ( ) ;
}
2009-03-13 07:50:07 +00:00
}
return newclass ;
}
2009-08-14 12:29:55 +00:00
/* use for subtyping so we know which srna is used for a PointerRNA */
static StructRNA * srna_from_ptr ( PointerRNA * ptr )
{
if ( ptr - > type = = & RNA_Struct ) {
return ptr - > data ;
}
else {
return ptr - > type ;
}
}
/* always returns a new ref, be sure to decref when done */
2009-11-07 22:07:46 +00:00
static PyObject * pyrna_struct_Subtype ( PointerRNA * ptr )
2009-07-10 18:09:53 +00:00
{
2009-08-14 12:29:55 +00:00
return pyrna_srna_Subtype ( srna_from_ptr ( ptr ) ) ;
2009-07-10 18:09:53 +00:00
}
2008-11-29 13:36:08 +00:00
/*-----------------------CreatePyObject---------------------------------*/
PyObject * pyrna_struct_CreatePyObject ( PointerRNA * ptr )
{
2009-03-21 06:55:30 +00:00
BPy_StructRNA * pyrna = NULL ;
2009-03-05 16:24:30 +00:00
2009-03-14 13:43:30 +00:00
if ( ptr - > data = = NULL & & ptr - > type = = NULL ) { /* Operator RNA has NULL data */
2009-03-05 16:24:30 +00:00
Py_RETURN_NONE ;
}
2009-07-10 04:25:49 +00:00
else {
2009-03-21 16:03:26 +00:00
PyTypeObject * tp = ( PyTypeObject * ) pyrna_struct_Subtype ( ptr ) ;
2009-03-21 06:55:30 +00:00
if ( tp ) {
pyrna = ( BPy_StructRNA * ) tp - > tp_alloc ( tp , 0 ) ;
2009-08-14 12:29:55 +00:00
Py_DECREF ( tp ) ; /* srna owns, cant hold a ref */
2009-03-21 06:55:30 +00:00
}
else {
fprintf ( stderr , " Could not make type \n " ) ;
pyrna = ( BPy_StructRNA * ) PyObject_NEW ( BPy_StructRNA , & pyrna_struct_Type ) ;
}
2009-03-11 17:28:37 +00:00
}
2009-07-10 04:25:49 +00:00
2008-11-29 13:36:08 +00:00
if ( ! pyrna ) {
PyErr_SetString ( PyExc_MemoryError , " couldn't create BPy_StructRNA object " ) ;
return NULL ;
}
2008-12-29 03:24:13 +00:00
pyrna - > ptr = * ptr ;
2009-07-26 18:18:14 +00:00
pyrna - > freeptr = FALSE ;
2009-07-10 04:25:49 +00:00
// PyObSpit("NewStructRNA: ", (PyObject *)pyrna);
2008-11-29 13:36:08 +00:00
return ( PyObject * ) pyrna ;
}
PyObject * pyrna_prop_CreatePyObject ( PointerRNA * ptr , PropertyRNA * prop )
{
BPy_PropertyRNA * pyrna ;
2010-02-15 23:43:51 +00:00
PyTypeObject * type ;
if ( RNA_property_type ( prop ) = = PROP_COLLECTION ) type = & pyrna_prop_collection_Type ;
else if ( RNA_property_array_check ( ptr , prop ) ) type = & pyrna_prop_array_Type ;
else type = & pyrna_prop_Type ;
2008-11-29 13:36:08 +00:00
2010-02-15 23:43:51 +00:00
pyrna = ( BPy_PropertyRNA * ) PyObject_NEW ( BPy_PropertyRNA , type ) ;
2008-11-29 13:36:08 +00:00
if ( ! pyrna ) {
PyErr_SetString ( PyExc_MemoryError , " couldn't create BPy_rna object " ) ;
return NULL ;
}
pyrna - > ptr = * ptr ;
pyrna - > prop = prop ;
2009-09-06 15:13:57 +00:00
pyrna - > arraydim = 0 ;
pyrna - > arrayoffset = 0 ;
2008-11-29 13:36:08 +00:00
return ( PyObject * ) pyrna ;
}
2009-11-08 01:13:19 +00:00
void BPY_rna_init ( void )
2008-11-29 13:36:08 +00:00
{
2009-06-22 04:26:48 +00:00
# ifdef USE_MATHUTILS // register mathutils callbacks, ok to run more then once.
2009-06-25 10:11:37 +00:00
mathutils_rna_array_cb_index = Mathutils_RegisterCallback ( & mathutils_rna_array_cb ) ;
2009-06-23 13:34:45 +00:00
mathutils_rna_matrix_cb_index = Mathutils_RegisterCallback ( & mathutils_rna_matrix_cb ) ;
2009-06-22 04:26:48 +00:00
# endif
2009-11-08 01:13:19 +00:00
2009-03-13 07:50:07 +00:00
if ( PyType_Ready ( & pyrna_struct_Type ) < 0 )
2009-11-08 01:13:19 +00:00
return ;
2009-03-13 07:50:07 +00:00
if ( PyType_Ready ( & pyrna_prop_Type ) < 0 )
2009-11-08 01:13:19 +00:00
return ;
2010-02-15 23:43:51 +00:00
if ( PyType_Ready ( & pyrna_prop_array_Type ) < 0 )
return ;
if ( PyType_Ready ( & pyrna_prop_collection_Type ) < 0 )
return ;
2009-11-08 01:13:19 +00:00
}
/* bpy.data from python */
static PointerRNA * rna_module_ptr = NULL ;
PyObject * BPY_rna_module ( void )
{
BPy_StructRNA * pyrna ;
PointerRNA ptr ;
2009-03-13 07:50:07 +00:00
2008-11-29 13:36:08 +00:00
/* for now, return the base RNA type rather then a real module */
RNA_main_pointer_create ( G . main , & ptr ) ;
2009-08-15 09:53:38 +00:00
pyrna = ( BPy_StructRNA * ) pyrna_struct_CreatePyObject ( & ptr ) ;
2008-11-29 13:36:08 +00:00
2009-08-15 09:53:38 +00:00
rna_module_ptr = & pyrna - > ptr ;
return ( PyObject * ) pyrna ;
}
void BPY_update_rna_module ( void )
{
RNA_main_pointer_create ( G . main , rna_module_ptr ) ;
2008-11-29 13:36:08 +00:00
}
2008-12-16 16:32:48 +00:00
2009-03-13 07:50:07 +00:00
#if 0
2008-12-16 16:32:48 +00:00
/* This is a way we can access docstrings for RNA types
* without having the datatypes in blender */
PyObject * BPY_rna_doc ( void )
{
PointerRNA ptr ;
/* for now, return the base RNA type rather then a real module */
RNA_blender_rna_pointer_create ( & ptr ) ;
return pyrna_struct_CreatePyObject ( & ptr ) ;
}
2009-03-13 07:50:07 +00:00
# endif
2008-12-16 16:32:48 +00:00
2009-03-11 17:28:37 +00:00
2009-03-21 06:55:30 +00:00
/* pyrna_basetype_* - BPy_BaseTypeRNA is just a BPy_PropertyRNA struct with a differnt type
* the self - > ptr and self - > prop are always set to the " structs " collection */
//---------------getattr--------------------------------------------
2009-11-16 19:03:40 +00:00
static PyObject * pyrna_basetype_getattro ( BPy_BaseTypeRNA * self , PyObject * pyname )
2009-03-21 06:55:30 +00:00
{
PointerRNA newptr ;
PyObject * ret ;
2010-01-22 14:06:42 +00:00
char * name = _PyUnicode_AsString ( pyname ) ;
2009-03-11 17:28:37 +00:00
2010-01-22 14:06:42 +00:00
if ( strcmp ( name , " register " ) = = 0 ) {
/* this is called so often, make an exception and save a full lookup on all types */
ret = PyObject_GenericGetAttr ( ( PyObject * ) self , pyname ) ;
}
else if ( RNA_property_collection_lookup_string ( & self - > ptr , self - > prop , name , & newptr ) ) {
2009-04-11 15:05:42 +00:00
ret = pyrna_struct_Subtype ( & newptr ) ;
if ( ret = = NULL ) {
2009-07-09 08:06:26 +00:00
PyErr_Format ( PyExc_SystemError , " bpy.types.%.200s subtype could not be generated, this is a bug! " , _PyUnicode_AsString ( pyname ) ) ;
2009-04-11 15:05:42 +00:00
}
2009-03-11 17:28:37 +00:00
}
2009-11-08 01:13:19 +00:00
else {
#if 0
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_AttributeError , " bpy.types.%.200s RNA_Struct does not exist " , _PyUnicode_AsString ( pyname ) ) ;
2009-03-21 06:55:30 +00:00
return NULL ;
2009-11-08 01:13:19 +00:00
# endif
/* The error raised here will be displayed */
ret = PyObject_GenericGetAttr ( ( PyObject * ) self , pyname ) ;
2009-03-21 06:55:30 +00:00
}
2009-11-08 01:13:19 +00:00
return ret ;
2009-03-21 06:55:30 +00:00
}
static PyObject * pyrna_basetype_dir ( BPy_BaseTypeRNA * self ) ;
static struct PyMethodDef pyrna_basetype_methods [ ] = {
{ " __dir__ " , ( PyCFunction ) pyrna_basetype_dir , METH_NOARGS , " " } ,
2009-08-15 05:05:23 +00:00
{ " register " , ( PyCFunction ) pyrna_basetype_register , METH_O , " " } ,
{ " unregister " , ( PyCFunction ) pyrna_basetype_unregister , METH_O , " " } ,
2009-03-21 06:55:30 +00:00
{ NULL , NULL , 0 , NULL }
} ;
static PyObject * pyrna_basetype_dir ( BPy_BaseTypeRNA * self )
{
PyObject * list , * name ;
PyMethodDef * meth ;
list = pyrna_prop_keys ( self ) ; /* like calling structs.keys(), avoids looping here */
for ( meth = pyrna_basetype_methods ; meth - > ml_name ; meth + + ) {
name = PyUnicode_FromString ( meth - > ml_name ) ;
PyList_Append ( list , name ) ;
Py_DECREF ( name ) ;
}
return list ;
}
2009-04-11 16:17:39 +00:00
PyTypeObject pyrna_basetype_Type = BLANK_PYTHON_TYPE ;
2009-03-21 06:55:30 +00:00
PyObject * BPY_rna_types ( void )
{
BPy_BaseTypeRNA * self ;
2009-04-07 15:20:12 +00:00
2009-04-11 16:17:39 +00:00
if ( ( pyrna_basetype_Type . tp_flags & Py_TPFLAGS_READY ) = = 0 ) {
pyrna_basetype_Type . tp_name = " RNA_Types " ;
pyrna_basetype_Type . tp_basicsize = sizeof ( BPy_BaseTypeRNA ) ;
pyrna_basetype_Type . tp_getattro = ( getattrofunc ) pyrna_basetype_getattro ;
pyrna_basetype_Type . tp_flags = Py_TPFLAGS_DEFAULT ;
pyrna_basetype_Type . tp_methods = pyrna_basetype_methods ;
if ( PyType_Ready ( & pyrna_basetype_Type ) < 0 )
return NULL ;
}
2009-03-13 07:50:07 +00:00
2009-03-21 06:55:30 +00:00
self = ( BPy_BaseTypeRNA * ) PyObject_NEW ( BPy_BaseTypeRNA , & pyrna_basetype_Type ) ;
2010-01-30 13:15:39 +00:00
self - > arraydim = self - > arrayoffset = 0 ; /* unused but better set */
2009-03-21 06:55:30 +00:00
/* avoid doing this lookup for every getattr */
RNA_blender_rna_pointer_create ( & self - > ptr ) ;
self - > prop = RNA_struct_find_property ( & self - > ptr , " structs " ) ;
2010-01-30 13:15:39 +00:00
2009-03-21 06:55:30 +00:00
return ( PyObject * ) self ;
2009-03-11 17:28:37 +00:00
}
2009-03-16 15:54:43 +00:00
2009-12-30 22:14:32 +00:00
StructRNA * pyrna_struct_as_srna ( PyObject * self )
2009-08-15 05:05:23 +00:00
{
2009-10-21 17:56:26 +00:00
BPy_StructRNA * py_srna = NULL ;
2009-08-16 12:29:46 +00:00
StructRNA * srna ;
2009-08-22 17:06:10 +00:00
/* ack, PyObject_GetAttrString wont look up this types tp_dict first :/ */
if ( PyType_Check ( self ) ) {
2009-10-31 13:31:23 +00:00
py_srna = ( BPy_StructRNA * ) PyDict_GetItemString ( ( ( PyTypeObject * ) self ) - > tp_dict , " bl_rna " ) ;
2009-08-22 17:06:10 +00:00
Py_XINCREF ( py_srna ) ;
}
if ( py_srna = = NULL )
2009-10-31 13:31:23 +00:00
py_srna = ( BPy_StructRNA * ) PyObject_GetAttrString ( self , " bl_rna " ) ;
2009-08-15 05:05:23 +00:00
if ( py_srna = = NULL ) {
2009-10-31 13:31:23 +00:00
PyErr_SetString ( PyExc_SystemError , " internal error, self had no bl_rna attribute, should never happen. " ) ;
2009-08-15 05:05:23 +00:00
return NULL ;
}
2009-08-16 12:29:46 +00:00
if ( ! BPy_StructRNA_Check ( py_srna ) ) {
2009-10-31 13:31:23 +00:00
PyErr_Format ( PyExc_SystemError , " internal error, bl_rna was of type %.200s, instead of %.200s instance. " , Py_TYPE ( py_srna ) - > tp_name , pyrna_struct_Type . tp_name ) ;
2009-08-16 12:29:46 +00:00
Py_DECREF ( py_srna ) ;
return NULL ;
}
if ( py_srna - > ptr . type ! = & RNA_Struct ) {
2009-10-31 13:31:23 +00:00
PyErr_SetString ( PyExc_SystemError , " internal error, bl_rna was not a RNA_Struct type of rna struct. " ) ;
2009-08-15 05:05:23 +00:00
Py_DECREF ( py_srna ) ;
return NULL ;
}
2009-08-16 12:29:46 +00:00
srna = py_srna - > ptr . data ;
2009-08-15 05:05:23 +00:00
Py_DECREF ( py_srna ) ;
2009-08-16 12:29:46 +00:00
return srna ;
2009-08-15 05:05:23 +00:00
}
2009-03-16 15:54:43 +00:00
/* Orphan functions, not sure where they should go */
2009-08-09 10:05:33 +00:00
/* get the srna for methods attached to types */
2009-08-11 02:27:25 +00:00
/* */
2009-12-30 22:14:32 +00:00
StructRNA * srna_from_self ( PyObject * self )
2009-08-09 10:05:33 +00:00
{
2009-08-11 02:27:25 +00:00
/* a bit sloppy but would cause a very confusing bug if
* an error happened to be set here */
PyErr_Clear ( ) ;
2010-01-19 00:59:36 +00:00
2009-08-09 10:05:33 +00:00
if ( self = = NULL ) {
return NULL ;
}
2010-02-12 21:14:01 +00:00
else if ( PyCapsule_CheckExact ( self ) ) {
return PyCapsule_GetPointer ( self , NULL ) ;
2009-08-09 10:05:33 +00:00
}
2009-08-11 02:27:25 +00:00
else if ( PyType_Check ( self ) = = 0 ) {
return NULL ;
}
/* These cases above not errors, they just mean the type was not compatible
* After this any errors will be raised in the script */
2009-08-09 10:05:33 +00:00
2009-08-15 05:05:23 +00:00
return pyrna_struct_as_srna ( self ) ;
2009-08-09 10:05:33 +00:00
}
2009-11-20 20:58:46 +00:00
static int deferred_register_prop ( StructRNA * srna , PyObject * item , PyObject * key , PyObject * dummy_args )
2009-08-22 17:30:47 +00:00
{
2009-11-20 20:58:46 +00:00
/* We only care about results from C which
* are for sure types , save some time with error */
if ( PyTuple_CheckExact ( item ) & & PyTuple_GET_SIZE ( item ) = = 2 ) {
2009-08-22 17:30:47 +00:00
define operator properties in the class, similar to django fields
# Before
[
bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
2009-10-31 16:40:14 +00:00
PyObject * py_func_ptr , * py_kw , * py_srna_cobject , * py_ret ;
2009-12-11 00:51:14 +00:00
PyObject * ( * pyfunc ) ( PyObject * , PyObject * , PyObject * ) ;
2009-08-22 17:30:47 +00:00
2010-02-12 21:14:01 +00:00
if ( PyArg_ParseTuple ( item , " O!O! " , & PyCapsule_Type , & py_func_ptr , & PyDict_Type , & py_kw ) ) {
2009-08-22 17:30:47 +00:00
2009-12-11 00:51:14 +00:00
if ( * _PyUnicode_AsString ( key ) = = ' _ ' ) {
PyErr_Format ( PyExc_ValueError , " StructRNA \" %.200s \" registration error: %.200s could not register because the property starts with an '_' \n " , RNA_struct_identifier ( srna ) , _PyUnicode_AsString ( key ) ) ;
Py_DECREF ( dummy_args ) ;
return - 1 ;
}
2010-02-12 21:14:01 +00:00
pyfunc = PyCapsule_GetPointer ( py_func_ptr , NULL ) ;
py_srna_cobject = PyCapsule_New ( srna , NULL , NULL ) ;
define operator properties in the class, similar to django fields
# Before
[
bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
2009-10-31 16:40:14 +00:00
2009-11-20 20:58:46 +00:00
/* not 100% nice :/, modifies the dict passed, should be ok */
PyDict_SetItemString ( py_kw , " attr " , key ) ;
define operator properties in the class, similar to django fields
# Before
[
bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
2009-10-31 16:40:14 +00:00
2009-11-20 20:58:46 +00:00
py_ret = pyfunc ( py_srna_cobject , dummy_args , py_kw ) ;
Py_DECREF ( py_srna_cobject ) ;
if ( py_ret ) {
Py_DECREF ( py_ret ) ;
2009-08-22 17:30:47 +00:00
}
else {
2009-11-20 20:58:46 +00:00
PyErr_Print ( ) ;
define operator properties in the class, similar to django fields
# Before
[
bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
2009-10-31 16:40:14 +00:00
PyErr_Clear ( ) ;
2010-02-01 22:04:33 +00:00
// PyLineSpit();
2009-11-20 20:58:46 +00:00
PyErr_Format ( PyExc_ValueError , " StructRNA \" %.200s \" registration error: %.200s could not register \n " , RNA_struct_identifier ( srna ) , _PyUnicode_AsString ( key ) ) ;
2010-02-01 22:04:33 +00:00
2009-11-20 20:58:46 +00:00
Py_DECREF ( dummy_args ) ;
return - 1 ;
2009-08-22 17:30:47 +00:00
}
}
2009-11-20 20:58:46 +00:00
else {
/* Since this is a class dict, ignore args that can't be passed */
/* for testing only */
/* PyObSpit("Why doesn't this work??", item);
PyErr_Print ( ) ; */
PyErr_Clear ( ) ;
}
}
return 0 ;
}
int pyrna_deferred_register_props ( StructRNA * srna , PyObject * class_dict )
{
PyObject * item , * key ;
PyObject * order ;
PyObject * dummy_args ;
Py_ssize_t pos = 0 ;
int ret ;
dummy_args = PyTuple_New ( 0 ) ;
order = PyDict_GetItemString ( class_dict , " order " ) ;
2010-01-15 22:40:33 +00:00
if ( order = = NULL )
PyErr_Clear ( ) ;
2009-11-20 20:58:46 +00:00
if ( order & & PyList_Check ( order ) ) {
for ( pos = 0 ; pos < PyList_GET_SIZE ( order ) ; pos + + ) {
key = PyList_GET_ITEM ( order , pos ) ;
item = PyDict_GetItem ( class_dict , key ) ;
ret = deferred_register_prop ( srna , item , key , dummy_args ) ;
if ( ret = = - 1 )
break ;
}
}
else {
while ( PyDict_Next ( class_dict , & pos , & key , & item ) ) {
ret = deferred_register_prop ( srna , item , key , dummy_args ) ;
if ( ret = = - 1 )
break ;
}
2009-08-22 17:30:47 +00:00
}
Py_DECREF ( dummy_args ) ;
2009-11-20 20:58:46 +00:00
define operator properties in the class, similar to django fields
# Before
[
bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
2009-10-31 16:40:14 +00:00
return 0 ;
2009-08-22 17:30:47 +00:00
}
2009-04-19 13:37:59 +00:00
/*-------------------- Type Registration ------------------------*/
static int rna_function_arg_count ( FunctionRNA * func )
{
const ListBase * lb = RNA_function_defined_parameters ( func ) ;
PropertyRNA * parm ;
Link * link ;
int count = 1 ;
for ( link = lb - > first ; link ; link = link - > next ) {
parm = ( PropertyRNA * ) link ;
2010-01-24 10:51:59 +00:00
if ( ! ( RNA_property_flag ( parm ) & PROP_OUTPUT ) )
2009-04-19 13:37:59 +00:00
count + + ;
}
return count ;
}
static int bpy_class_validate ( PointerRNA * dummyptr , void * py_data , int * have_function )
{
const ListBase * lb ;
Link * link ;
FunctionRNA * func ;
PropertyRNA * prop ;
StructRNA * srna = dummyptr - > type ;
const char * class_type = RNA_struct_identifier ( srna ) ;
PyObject * py_class = ( PyObject * ) py_data ;
PyObject * base_class = RNA_struct_py_type_get ( srna ) ;
PyObject * item , * fitem ;
PyObject * py_arg_count ;
int i , flag , arg_count , func_arg_count ;
2009-12-24 16:10:26 +00:00
const char * py_class_name = ( ( PyTypeObject * ) py_class ) - > tp_name ; // __name__
2009-04-19 13:37:59 +00:00
if ( base_class ) {
if ( ! PyObject_IsSubclass ( py_class , base_class ) ) {
2009-12-24 16:10:26 +00:00
PyErr_Format ( PyExc_TypeError , " expected %.200s subclass of class \" %.200s \" " , class_type , py_class_name ) ;
2009-04-19 13:37:59 +00:00
return - 1 ;
}
}
/* verify callback functions */
lb = RNA_struct_defined_functions ( srna ) ;
i = 0 ;
for ( link = lb - > first ; link ; link = link - > next ) {
func = ( FunctionRNA * ) link ;
flag = RNA_function_flag ( func ) ;
if ( ! ( flag & FUNC_REGISTER ) )
continue ;
item = PyObject_GetAttrString ( py_class , RNA_function_identifier ( func ) ) ;
have_function [ i ] = ( item ! = NULL ) ;
i + + ;
if ( item = = NULL ) {
if ( ( flag & FUNC_REGISTER_OPTIONAL ) = = 0 ) {
2009-12-24 16:10:26 +00:00
PyErr_Format ( PyExc_AttributeError , " expected %.200s, %.200s class to have an \" %.200s \" attribute " , class_type , py_class_name , RNA_function_identifier ( func ) ) ;
2009-04-19 13:37:59 +00:00
return - 1 ;
}
PyErr_Clear ( ) ;
}
else {
Py_DECREF ( item ) ; /* no need to keep a ref, the class owns it */
if ( PyMethod_Check ( item ) )
fitem = PyMethod_Function ( item ) ; /* py 2.x */
else
fitem = item ; /* py 3.x */
if ( PyFunction_Check ( fitem ) = = 0 ) {
2009-12-24 16:10:26 +00:00
PyErr_Format ( PyExc_TypeError , " expected %.200s, %.200s class \" %.200s \" attribute to be a function " , class_type , py_class_name , RNA_function_identifier ( func ) ) ;
2009-04-19 13:37:59 +00:00
return - 1 ;
}
func_arg_count = rna_function_arg_count ( func ) ;
if ( func_arg_count > = 0 ) { /* -1 if we dont care*/
py_arg_count = PyObject_GetAttrString ( PyFunction_GET_CODE ( fitem ) , " co_argcount " ) ;
arg_count = PyLong_AsSsize_t ( py_arg_count ) ;
Py_DECREF ( py_arg_count ) ;
if ( arg_count ! = func_arg_count ) {
2010-02-14 11:21:21 +00:00
PyErr_Format ( PyExc_AttributeError , " expected %.200s, %.200s class \" %.200s \" function to have %d args, found %d " , class_type , py_class_name , RNA_function_identifier ( func ) , func_arg_count , arg_count ) ;
2009-04-19 13:37:59 +00:00
return - 1 ;
}
}
}
}
/* verify properties */
lb = RNA_struct_defined_properties ( srna ) ;
for ( link = lb - > first ; link ; link = link - > next ) {
2009-12-24 16:10:26 +00:00
const char * identifier ;
2009-04-19 13:37:59 +00:00
prop = ( PropertyRNA * ) link ;
flag = RNA_property_flag ( prop ) ;
if ( ! ( flag & PROP_REGISTER ) )
continue ;
2009-10-31 13:31:23 +00:00
identifier = RNA_property_identifier ( prop ) ;
2009-04-19 13:37:59 +00:00
item = PyObject_GetAttrString ( py_class , identifier ) ;
if ( item = = NULL ) {
2009-10-31 18:48:58 +00:00
/* Sneaky workaround to use the class name as the bl_idname */
2009-04-19 13:37:59 +00:00
2010-01-05 20:19:54 +00:00
# define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \
if ( strcmp ( identifier , rna_attr ) = = 0 ) { \
item = PyObject_GetAttrString ( py_class , py_attr ) ; \
if ( item & & item ! = Py_None ) { \
2010-01-24 10:51:59 +00:00
if ( pyrna_py_to_prop ( dummyptr , prop , NULL , NULL , item , " validating class error: " ) ! = 0 ) { \
2010-01-05 20:19:54 +00:00
Py_DECREF ( item ) ; \
return - 1 ; \
} \
} \
Py_XDECREF ( item ) ; \
} \
2009-04-19 13:37:59 +00:00
2010-01-05 20:19:54 +00:00
BPY_REPLACEMENT_STRING ( " bl_idname " , " __name__ " ) ;
BPY_REPLACEMENT_STRING ( " bl_description " , " __doc__ " ) ;
2009-10-31 18:48:58 +00:00
2010-01-05 20:19:54 +00:00
# undef BPY_REPLACEMENT_STRING
2009-12-24 19:50:43 +00:00
2009-10-31 18:48:58 +00:00
if ( item = = NULL & & ( ( ( flag & PROP_REGISTER_OPTIONAL ) ! = PROP_REGISTER_OPTIONAL ) ) ) {
2009-12-24 16:10:26 +00:00
PyErr_Format ( PyExc_AttributeError , " expected %.200s, %.200s class to have an \" %.200s \" attribute " , class_type , py_class_name , identifier ) ;
2009-04-19 13:37:59 +00:00
return - 1 ;
}
PyErr_Clear ( ) ;
}
else {
Py_DECREF ( item ) ; /* no need to keep a ref, the class owns it */
2010-01-24 10:51:59 +00:00
if ( pyrna_py_to_prop ( dummyptr , prop , NULL , NULL , item , " validating class error: " ) ! = 0 )
2009-04-19 13:37:59 +00:00
return - 1 ;
}
}
return 0 ;
}
extern void BPY_update_modules ( void ) ; //XXX temp solution
2010-01-02 10:42:38 +00:00
/* TODO - multiple return values like with rna functions */
2009-04-19 13:37:59 +00:00
static int bpy_class_call ( PointerRNA * ptr , FunctionRNA * func , ParameterList * parms )
{
PyObject * args ;
PyObject * ret = NULL , * py_class , * py_class_instance , * item , * parmitem ;
2010-01-02 10:42:38 +00:00
PropertyRNA * parm ;
2009-04-19 13:37:59 +00:00
ParameterIterator iter ;
PointerRNA funcptr ;
2010-01-02 10:42:38 +00:00
int err = 0 , i , flag , ret_len = 0 ;
PropertyRNA * pret_single = NULL ;
void * retdata_single = NULL ;
2009-04-19 13:37:59 +00:00
2009-08-07 16:20:19 +00:00
PyGILState_STATE gilstate ;
2009-04-19 13:37:59 +00:00
2009-08-07 16:20:19 +00:00
bContext * C = BPy_GetContext ( ) ; // XXX - NEEDS FIXING, QUITE BAD.
bpy_context_set ( C , & gilstate ) ;
2009-04-19 13:37:59 +00:00
py_class = RNA_struct_py_type_get ( ptr - > type ) ;
2009-05-20 05:35:53 +00:00
item = pyrna_struct_CreatePyObject ( ptr ) ;
if ( item = = NULL ) {
py_class_instance = NULL ;
}
else if ( item = = Py_None ) { /* probably wont ever happen but possible */
Py_DECREF ( item ) ;
py_class_instance = NULL ;
}
else {
args = PyTuple_New ( 1 ) ;
PyTuple_SET_ITEM ( args , 0 , item ) ;
py_class_instance = PyObject_Call ( py_class , args , NULL ) ;
Py_DECREF ( args ) ;
}
2009-04-19 13:37:59 +00:00
if ( py_class_instance ) { /* Initializing the class worked, now run its invoke function */
item = PyObject_GetAttrString ( py_class , RNA_function_identifier ( func ) ) ;
2010-01-02 10:42:38 +00:00
// flag= RNA_function_flag(func);
2009-04-19 13:37:59 +00:00
if ( item ) {
RNA_pointer_create ( NULL , & RNA_Function , func , & funcptr ) ;
2009-11-20 10:00:54 +00:00
args = PyTuple_New ( rna_function_arg_count ( func ) ) ; /* first arg is included in 'item' */
2009-04-19 13:37:59 +00:00
PyTuple_SET_ITEM ( args , 0 , py_class_instance ) ;
RNA_parameter_list_begin ( parms , & iter ) ;
/* parse function parameters */
for ( i = 1 ; iter . valid ; RNA_parameter_list_next ( & iter ) ) {
parm = iter . parm ;
2010-01-02 10:42:38 +00:00
flag = RNA_property_flag ( parm ) ;
/* only useful for single argument returns, we'll need another list loop for multiple */
2010-01-24 10:51:59 +00:00
if ( flag & PROP_OUTPUT ) {
2010-01-02 10:42:38 +00:00
ret_len + + ;
if ( pret_single = = NULL ) {
pret_single = parm ;
retdata_single = iter . data ;
}
2009-04-19 13:37:59 +00:00
continue ;
}
2010-01-24 10:51:59 +00:00
parmitem = pyrna_param_to_py ( & funcptr , parms , parm , iter . data ) ;
2009-04-19 13:37:59 +00:00
PyTuple_SET_ITEM ( args , i , parmitem ) ;
i + + ;
}
ret = PyObject_Call ( item , args , NULL ) ;
2010-01-02 19:01:19 +00:00
RNA_parameter_list_end ( & iter ) ;
2009-04-19 13:37:59 +00:00
Py_DECREF ( item ) ;
2009-05-20 05:35:53 +00:00
Py_DECREF ( args ) ;
2009-04-19 13:37:59 +00:00
}
else {
2009-11-20 10:00:54 +00:00
PyErr_Print ( ) ;
PyErr_Clear ( ) ;
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_TypeError , " could not find function %.200s in %.200s to execute callback. " , RNA_function_identifier ( func ) , RNA_struct_identifier ( ptr - > type ) ) ;
2009-04-19 13:37:59 +00:00
err = - 1 ;
}
}
else {
2009-07-17 02:31:28 +00:00
PyErr_Format ( PyExc_RuntimeError , " could not create instance of %.200s to call callback function %.200s. " , RNA_struct_identifier ( ptr - > type ) , RNA_function_identifier ( func ) ) ;
2009-04-19 13:37:59 +00:00
err = - 1 ;
}
if ( ret = = NULL ) { /* covers py_class_instance failing too */
err = - 1 ;
}
else {
2010-01-02 10:42:38 +00:00
if ( ret_len = = 1 ) {
2010-01-24 10:51:59 +00:00
err = pyrna_py_to_prop ( & funcptr , pret_single , parms , retdata_single , ret , " calling class function: " ) ;
2010-01-02 10:42:38 +00:00
}
else if ( ret_len > 1 ) {
if ( PyTuple_Check ( ret ) = = 0 ) {
PyErr_Format ( PyExc_RuntimeError , " expected class %.200s, function %.200s to return a tuple of size %d. " , RNA_struct_identifier ( ptr - > type ) , RNA_function_identifier ( func ) , ret_len ) ;
err = - 1 ;
}
else if ( PyTuple_GET_SIZE ( ret ) ! = ret_len ) {
PyErr_Format ( PyExc_RuntimeError , " class %.200s, function %.200s to returned %d items, expected %d. " , RNA_struct_identifier ( ptr - > type ) , RNA_function_identifier ( func ) , PyTuple_GET_SIZE ( ret ) , ret_len ) ;
err = - 1 ;
}
else {
RNA_parameter_list_begin ( parms , & iter ) ;
/* parse function parameters */
for ( i = 0 ; iter . valid ; RNA_parameter_list_next ( & iter ) ) {
parm = iter . parm ;
flag = RNA_property_flag ( parm ) ;
/* only useful for single argument returns, we'll need another list loop for multiple */
2010-01-24 10:51:59 +00:00
if ( flag & PROP_OUTPUT ) {
err = pyrna_py_to_prop ( & funcptr , parm , parms , iter . data , PyTuple_GET_ITEM ( ret , i + + ) , " calling class function: " ) ;
2010-01-02 10:42:38 +00:00
if ( err )
break ;
}
}
2010-01-02 19:01:19 +00:00
RNA_parameter_list_end ( & iter ) ;
2010-01-02 10:42:38 +00:00
}
}
2009-04-19 13:37:59 +00:00
Py_DECREF ( ret ) ;
}
2009-07-23 13:48:15 +00:00
if ( err ! = 0 ) {
PyErr_Print ( ) ;
PyErr_Clear ( ) ;
}
2009-08-07 16:20:19 +00:00
bpy_context_clear ( C , & gilstate ) ;
2009-04-19 13:37:59 +00:00
return err ;
}
static void bpy_class_free ( void * pyob_ptr )
{
2009-08-14 12:29:55 +00:00
PyObject * self = ( PyObject * ) pyob_ptr ;
PyGILState_STATE gilstate ;
gilstate = PyGILState_Ensure ( ) ;
2010-02-15 11:24:43 +00:00
// breaks re-registering classes
// PyDict_Clear(((PyTypeObject*)self)->tp_dict);
//
// remove the rna attribute instead.
PyDict_DelItemString ( ( ( PyTypeObject * ) self ) - > tp_dict , " bl_rna " ) ;
if ( PyErr_Occurred ( ) )
PyErr_Clear ( ) ;
2009-08-14 12:29:55 +00:00
2009-05-28 02:03:48 +00:00
if ( G . f & G_DEBUG ) {
2009-08-14 12:29:55 +00:00
if ( self - > ob_refcnt > 1 ) {
PyObSpit ( " zombie class - ref should be 1 " , self ) ;
}
2009-05-28 02:03:48 +00:00
}
2009-08-14 12:29:55 +00:00
2009-04-19 13:37:59 +00:00
Py_DECREF ( ( PyObject * ) pyob_ptr ) ;
2009-08-14 12:29:55 +00:00
PyGILState_Release ( gilstate ) ;
}
2009-08-15 09:53:38 +00:00
void pyrna_alloc_types ( void )
{
PyGILState_STATE gilstate ;
PointerRNA ptr ;
PropertyRNA * prop ;
2009-08-15 10:50:30 +00:00
gilstate = PyGILState_Ensure ( ) ;
2009-08-15 09:53:38 +00:00
/* avoid doing this lookup for every getattr */
RNA_blender_rna_pointer_create ( & ptr ) ;
prop = RNA_struct_find_property ( & ptr , " structs " ) ;
RNA_PROP_BEGIN ( & ptr , itemptr , prop ) {
Py_DECREF ( pyrna_struct_Subtype ( & itemptr ) ) ;
}
RNA_PROP_END ;
PyGILState_Release ( gilstate ) ;
}
2009-08-14 12:29:55 +00:00
void pyrna_free_types ( void )
{
PointerRNA ptr ;
PropertyRNA * prop ;
/* avoid doing this lookup for every getattr */
RNA_blender_rna_pointer_create ( & ptr ) ;
prop = RNA_struct_find_property ( & ptr , " structs " ) ;
RNA_PROP_BEGIN ( & ptr , itemptr , prop ) {
StructRNA * srna = srna_from_ptr ( & itemptr ) ;
void * py_ptr = RNA_struct_py_type_get ( srna ) ;
if ( py_ptr ) {
#if 0 // XXX - should be able to do this but makes python crash on exit
bpy_class_free ( py_ptr ) ;
# endif
RNA_struct_py_type_set ( srna , NULL ) ;
}
}
RNA_PROP_END ;
2009-12-24 19:50:43 +00:00
2009-04-19 13:37:59 +00:00
}
2009-08-16 04:59:11 +00:00
/* Note! MemLeak XXX
*
* There is currently a bug where moving registering a python class does
* not properly manage refcounts from the python class , since the srna owns
* the python class this should not be so tricky but changing the references as
* youd expect when changing ownership crashes blender on exit so I had to comment out
* the decref . This is not so bad because the leak only happens when re - registering ( hold F8 )
* - Should still be fixed - Campbell
* */
2009-08-15 05:05:23 +00:00
PyObject * pyrna_basetype_register ( PyObject * self , PyObject * py_class )
2009-04-19 13:37:59 +00:00
{
bContext * C = NULL ;
ReportList reports ;
StructRegisterFunc reg ;
StructRNA * srna ;
2009-08-15 09:53:38 +00:00
StructRNA * srna_new ;
2.5: RNA, defining enums, pointers and collections properties is now
possible from python, but it's still work in progress.
Pointers and collections are restricted to types derived from
IDPropertyGroup (same as for operators), because RNA knows how to
allocate/deallocate those.
Collections have .add() and .remove(number) functions that can be
used. The remove function should be fixed to take an other argument
than a number.
With the IDPropertyGroup restriction, pointers are more like nested
structs. They don't have add(), remove() yet, not sure where to put
them. Currently the pointer / nested struct is automatically allocated
in the get() function, this needs to be fixed, rule is that RNA get()
will not change any data for thread safety.
Also, it is only possible to add properties to structs after they have
been registered, which needs to be improved as well.
Example code:
http://www.pasteall.org/7201/python
2009-08-18 01:29:25 +00:00
PyObject * item ;
const char * identifier = " " ;
2009-04-19 13:37:59 +00:00
2010-02-14 11:21:21 +00:00
if ( PyDict_GetItemString ( ( ( PyTypeObject * ) py_class ) - > tp_dict , " bl_rna " ) ) {
2010-02-15 11:24:43 +00:00
PyErr_SetString ( PyExc_AttributeError , " bpy.types.register(): already registered as a subclass. " ) ;
2010-02-14 11:21:21 +00:00
return NULL ;
}
2009-08-15 05:05:23 +00:00
srna = pyrna_struct_as_srna ( py_class ) ;
if ( srna = = NULL )
2009-04-19 13:37:59 +00:00
return NULL ;
/* check that we have a register callback for this type */
2009-08-15 05:05:23 +00:00
reg = RNA_struct_register ( srna ) ;
2009-04-19 13:37:59 +00:00
if ( ! reg ) {
2010-02-15 11:24:43 +00:00
PyErr_SetString ( PyExc_ValueError , " bpy.types.register(): expected a Type subclassed from a registerable rna type (no register supported). " ) ;
2009-04-19 13:37:59 +00:00
return NULL ;
}
/* get the context, so register callback can do necessary refreshes */
2009-05-25 13:48:44 +00:00
C = BPy_GetContext ( ) ;
2009-04-19 13:37:59 +00:00
2.5: RNA, defining enums, pointers and collections properties is now
possible from python, but it's still work in progress.
Pointers and collections are restricted to types derived from
IDPropertyGroup (same as for operators), because RNA knows how to
allocate/deallocate those.
Collections have .add() and .remove(number) functions that can be
used. The remove function should be fixed to take an other argument
than a number.
With the IDPropertyGroup restriction, pointers are more like nested
structs. They don't have add(), remove() yet, not sure where to put
them. Currently the pointer / nested struct is automatically allocated
in the get() function, this needs to be fixed, rule is that RNA get()
will not change any data for thread safety.
Also, it is only possible to add properties to structs after they have
been registered, which needs to be improved as well.
Example code:
http://www.pasteall.org/7201/python
2009-08-18 01:29:25 +00:00
/* call the register callback with reports & identifier */
2009-06-18 19:48:55 +00:00
BKE_reports_init ( & reports , RPT_STORE ) ;
2.5: RNA, defining enums, pointers and collections properties is now
possible from python, but it's still work in progress.
Pointers and collections are restricted to types derived from
IDPropertyGroup (same as for operators), because RNA knows how to
allocate/deallocate those.
Collections have .add() and .remove(number) functions that can be
used. The remove function should be fixed to take an other argument
than a number.
With the IDPropertyGroup restriction, pointers are more like nested
structs. They don't have add(), remove() yet, not sure where to put
them. Currently the pointer / nested struct is automatically allocated
in the get() function, this needs to be fixed, rule is that RNA get()
will not change any data for thread safety.
Also, it is only possible to add properties to structs after they have
been registered, which needs to be improved as well.
Example code:
http://www.pasteall.org/7201/python
2009-08-18 01:29:25 +00:00
item = PyObject_GetAttrString ( py_class , " __name__ " ) ;
if ( item ) {
identifier = _PyUnicode_AsString ( item ) ;
Py_DECREF ( item ) ; /* no need to keep a ref, the class owns it */
}
srna_new = reg ( C , & reports , py_class , identifier , bpy_class_validate , bpy_class_call , bpy_class_free ) ;
2009-04-19 13:37:59 +00:00
2009-08-15 09:53:38 +00:00
if ( ! srna_new ) {
2009-04-19 13:37:59 +00:00
BPy_reports_to_error ( & reports ) ;
BKE_reports_clear ( & reports ) ;
return NULL ;
}
BKE_reports_clear ( & reports ) ;
2009-08-15 09:53:38 +00:00
pyrna_subtype_set_rna ( py_class , srna_new ) ; /* takes a ref to py_class */
/* old srna still references us, keep the check incase registering somehow can free it */
if ( RNA_struct_py_type_get ( srna ) ) {
RNA_struct_py_type_set ( srna , NULL ) ;
// Py_DECREF(py_class); // shuld be able to do this XXX since the old rna adds a new ref.
}
2009-04-19 13:37:59 +00:00
define operator properties in the class, similar to django fields
# Before
[
bpy.props.StringProperty(attr="path", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= ""),
bpy.props.BoolProperty(attr="use_modifiers", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True),
bpy.props.BoolProperty(attr="use_normals", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True),
bpy.props.BoolProperty(attr="use_uvs", name="Export UVs", description="Exort the active UV layer", default= True),
bpy.props.BoolProperty(attr="use_colors", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
]
# After
path = StringProperty(attr="", name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
use_modifiers = BoolProperty(attr="", name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
use_normals = BoolProperty(attr="", name="Export Normals", description="Export Normals for smooth and hard shaded faces", default= True)
use_uvs = BoolProperty(attr="", name="Export UVs", description="Exort the active UV layer", default= True)
use_colors = BoolProperty(attr="", name="Export Vertex Colors", description="Exort the active vertex color layer", default= True)
2009-10-31 16:40:14 +00:00
/* Can't use this because it returns a dict proxy
*
* item = PyObject_GetAttrString ( py_class , " __dict__ " ) ;
*/
item = ( ( PyTypeObject * ) py_class ) - > tp_dict ;
if ( item ) {
if ( pyrna_deferred_register_props ( srna_new , item ) ! = 0 ) {
return NULL ;
}
}
else {
PyErr_Clear ( ) ;
}
2009-08-22 17:30:47 +00:00
2009-04-19 13:37:59 +00:00
Py_RETURN_NONE ;
}
2009-08-15 05:05:23 +00:00
PyObject * pyrna_basetype_unregister ( PyObject * self , PyObject * py_class )
2009-04-19 13:37:59 +00:00
{
bContext * C = NULL ;
StructUnregisterFunc unreg ;
2009-08-15 05:05:23 +00:00
StructRNA * srna ;
2009-04-19 13:37:59 +00:00
2010-02-15 11:24:43 +00:00
/*if(PyDict_GetItemString(((PyTypeObject*)py_class)->tp_dict, "bl_rna")==NULL) {
PyErr_SetString ( PyExc_ValueError , " bpy.types.unregister(): not a registered as a subclass. " ) ;
return NULL ;
} */
2009-08-15 05:05:23 +00:00
srna = pyrna_struct_as_srna ( py_class ) ;
if ( srna = = NULL )
2009-04-19 13:37:59 +00:00
return NULL ;
/* check that we have a unregister callback for this type */
2009-08-15 05:05:23 +00:00
unreg = RNA_struct_unregister ( srna ) ;
2009-04-19 13:37:59 +00:00
if ( ! unreg ) {
2010-02-15 11:24:43 +00:00
PyErr_SetString ( PyExc_ValueError , " bpy.types.unregister(): expected a Type subclassed from a registerable rna type (no unregister supported). " ) ;
2009-04-19 13:37:59 +00:00
return NULL ;
}
/* get the context, so register callback can do necessary refreshes */
2009-05-25 13:48:44 +00:00
C = BPy_GetContext ( ) ;
2009-04-19 13:37:59 +00:00
/* call unregister */
2009-08-15 09:53:38 +00:00
unreg ( C , srna ) ; /* calls bpy_class_free, this decref's py_class */
2009-04-19 13:37:59 +00:00
2010-02-15 11:24:43 +00:00
PyDict_DelItemString ( ( ( PyTypeObject * ) py_class ) - > tp_dict , " bl_rna " ) ;
if ( PyErr_Occurred ( ) )
PyErr_Clear ( ) ; //return NULL;
2010-02-14 23:33:18 +00:00
2009-04-19 13:37:59 +00:00
Py_RETURN_NONE ;
}