From 32c91c897bd20439a236db24bfb6d2cababfd4bf Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Thu, 17 Nov 2005 18:35:11 +0000 Subject: [PATCH] -- Fix for the "LIB ERROR: base removed" problem; BPy Object was decrementing us.id when objects were destroyed but not always incrementing when created. The intent of modifying us.id is to make Python a "user" of the data so it persists even when it is deleted from Blenders UI. The original commit was unintentional but Ton thought the idea was OK. --- source/blender/python/api2_2x/Object.c | 143 +++++++++----------- source/blender/python/api2_2x/doc/Object.py | 7 +- 2 files changed, 67 insertions(+), 83 deletions(-) diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index f43e984557b..52c2aaf4519 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -113,7 +113,7 @@ struct rctf; /*****************************************************************************/ static PyObject *M_Object_New( PyObject * self, PyObject * args ); PyObject *M_Object_Get( PyObject * self, PyObject * args ); -static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args ); +static PyObject *M_Object_GetSelected( PyObject * self ); /* HELPER FUNCTION FOR PARENTING */ static PyObject *internal_makeParent(Object *parent, PyObject *py_child, int partype, int noninverse, int fast, int v1, int v2, int v3); @@ -147,7 +147,7 @@ struct PyMethodDef M_Object_methods[] = { M_Object_New_doc}, {"Get", ( PyCFunction ) M_Object_Get, METH_VARARGS, M_Object_Get_doc}, - {"GetSelected", ( PyCFunction ) M_Object_GetSelected, METH_VARARGS, + {"GetSelected", ( PyCFunction ) M_Object_GetSelected, METH_NOARGS, M_Object_GetSelected_doc}, {NULL, NULL, 0, NULL} }; @@ -169,13 +169,13 @@ static PyObject *Object_getDrawType( BPy_Object * self ); static PyObject *Object_getEuler( BPy_Object * self ); static PyObject *Object_getInverseMatrix( BPy_Object * self ); static PyObject *Object_getIpo( BPy_Object * self ); -static PyObject *Object_getLocation( BPy_Object * self, PyObject * args ); +static PyObject *Object_getLocation( BPy_Object * self ); static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args ); static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args ); static PyObject *Object_getName( BPy_Object * self ); static PyObject *Object_getParent( BPy_Object * self ); static PyObject *Object_getParentBoneName( BPy_Object * self ); -static PyObject *Object_getSize( BPy_Object * self, PyObject * args ); +static PyObject *Object_getSize( BPy_Object * self ); static PyObject *Object_getTimeOffset( BPy_Object * self ); static PyObject *Object_getTracked( BPy_Object * self ); static PyObject *Object_getType( BPy_Object * self ); @@ -187,7 +187,7 @@ static PyObject *Object_link( BPy_Object * self, PyObject * args ); static PyObject *Object_makeParent( BPy_Object * self, PyObject * args ); static PyObject *Object_makeParentDeform( BPy_Object * self, PyObject * args ); static PyObject *Object_makeParentVertex( BPy_Object * self, PyObject * args ); -static PyObject *Object_materialUsage( BPy_Object * self, PyObject * args ); +static PyObject *Object_materialUsage( void ); static PyObject *Object_getDupliVerts ( BPy_Object * self ); static PyObject *Object_getEffects( BPy_Object * self ); static PyObject *Object_setDeltaLocation( BPy_Object * self, PyObject * args ); @@ -302,7 +302,7 @@ If 'name_only' is nonzero or True, only the name of the datablock is returned"}, {"getInverseMatrix", ( PyCFunction ) Object_getInverseMatrix, METH_NOARGS, "Returns the object's inverse matrix"}, - {"getLocation", ( PyCFunction ) Object_getLocation, METH_VARARGS, + {"getLocation", ( PyCFunction ) Object_getLocation, METH_NOARGS, "Returns the object's location (x, y, z)"}, {"getMaterials", ( PyCFunction ) Object_getMaterials, METH_VARARGS, "(i = 0) - Returns list of materials assigned to the object.\n\ @@ -467,7 +467,7 @@ mode:\n\t0: make parent with inverse\n\t1: without inverse\n\ fast:\n\t0: update scene hierarchy automatically\n\t\ don't update scene hierarchy (faster). In this case, you must\n\t\ explicitely update the Scene hierarchy."}, - {"materialUsage", ( PyCFunction ) Object_materialUsage, METH_VARARGS, + {"materialUsage", ( PyCFunction ) Object_materialUsage, METH_NOARGS, "Determines the way the material is used and returns status.\n\ Possible arguments (provide as strings):\n\ \tData: Materials assigned to the object's data are shown. (default)\n\ @@ -594,16 +594,13 @@ PyTypeObject Object_Type = { PyObject *M_Object_New( PyObject * self, PyObject * args ) { struct Object *object; - BPy_Object *blen_object; int type; char *str_type; char *name = NULL; - if( !PyArg_ParseTuple( args, "s|s", &str_type, &name ) ) { - EXPP_ReturnPyObjError( PyExc_TypeError, - "string expected as argument" ); - return ( NULL ); - } + if( !PyArg_ParseTuple( args, "s|s", &str_type, &name ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "string expected as argument" ); if( strcmp( str_type, "Armature" ) == 0 ) type = OB_ARMATURE; @@ -691,12 +688,11 @@ PyObject *M_Object_New( PyObject * self, PyObject * args ) object->data = NULL; - /* Create a Python object from it. */ - blen_object = - ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); - blen_object->object = object; + /* user count be incremented in Object_CreatePyObject */ + object->id.us = 0; - return ( ( PyObject * ) blen_object ); + /* Create a Python object from it. */ + return Object_CreatePyObject( object ); } /*****************************************************************************/ @@ -706,7 +702,7 @@ PyObject *M_Object_New( PyObject * self, PyObject * args ) PyObject *M_Object_Get( PyObject * self, PyObject * args ) { struct Object *object; - BPy_Object *blen_object; + PyObject *blen_object; char *name = NULL; PyArg_ParseTuple( args, "|s", &name ); @@ -714,18 +710,12 @@ PyObject *M_Object_Get( PyObject * self, PyObject * args ) if( name != NULL ) { object = GetObjectByName( name ); - if( object == NULL ) { /* No object exists with the name specified in the argument name. */ - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "Unknown object specified." ) ); - } - blen_object = - ( BPy_Object * ) PyObject_NEW( BPy_Object, - &Object_Type ); - blen_object->object = object; - object->id.us++; + if( !object ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "Unknown object specified." ); - return ( ( PyObject * ) blen_object ); + return Object_CreatePyObject( object ); } else { /* No argument has been given. Return a list of all objects. */ PyObject *obj_list; @@ -734,27 +724,24 @@ PyObject *M_Object_Get( PyObject * self, PyObject * args ) obj_list = PyList_New( BLI_countlist( &( G.main->object ) ) ); - if( obj_list == NULL ) { - return ( EXPP_ReturnPyObjError( PyExc_SystemError, - "List creation failed." ) ); - } + if( !obj_list ) + return EXPP_ReturnPyObjError( PyExc_SystemError, + "List creation failed." ); link = G.main->object.first; index = 0; while( link ) { object = ( Object * ) link; - blen_object = - ( BPy_Object * ) PyObject_NEW( BPy_Object, - &Object_Type ); - blen_object->object = object; - object->id.us++; - - PyList_SetItem( obj_list, index, - ( PyObject * ) blen_object ); + blen_object = Object_CreatePyObject( object ); + if( !blen_object ) { + Py_DECREF( obj_list ); + Py_RETURN_NONE; + } + PyList_SetItem( obj_list, index, blen_object ); index++; link = link->next; } - return ( obj_list ); + return obj_list; } } @@ -762,9 +749,9 @@ PyObject *M_Object_Get( PyObject * self, PyObject * args ) /* Function: M_Object_GetSelected */ /* Python equivalent: Blender.Object.GetSelected */ /*****************************************************************************/ -static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args ) +static PyObject *M_Object_GetSelected( PyObject * self ) { - BPy_Object *blen_object; + PyObject *blen_object; PyObject *list; Base *base_iter; @@ -777,40 +764,34 @@ static PyObject *M_Object_GetSelected( PyObject * self, PyObject * args ) if( ( G.scene->basact ) && ( ( G.scene->basact->flag & SELECT ) && ( G.scene->basact->lay & G.vd->lay ) ) ) { + /* Active object is first in the list. */ - blen_object = - ( BPy_Object * ) PyObject_NEW( BPy_Object, - &Object_Type ); - if( blen_object == NULL ) { + blen_object = Object_CreatePyObject( G.scene->basact->object ); + if( !blen_object ) { Py_DECREF( list ); - Py_INCREF( Py_None ); - return ( Py_None ); + Py_RETURN_NONE; } - blen_object->object = G.scene->basact->object; - PyList_Append( list, ( PyObject * ) blen_object ); + PyList_Append( list, blen_object ); Py_DECREF( blen_object ); } base_iter = G.scene->base.first; while( base_iter ) { if( ( ( base_iter->flag & SELECT ) && - ( base_iter->lay & G.vd->lay ) ) && - ( base_iter != G.scene->basact ) ) { - blen_object = - ( BPy_Object * ) PyObject_NEW( BPy_Object, - &Object_Type ); - if( blen_object == NULL ) { + ( base_iter->lay & G.vd->lay ) ) && + ( base_iter != G.scene->basact ) ) { + + blen_object = Object_CreatePyObject( base_iter->object ); + if( !blen_object ) { Py_DECREF( list ); - Py_INCREF( Py_None ); - return ( Py_None ); + Py_RETURN_NONE; } - blen_object->object = base_iter->object; - PyList_Append( list, ( PyObject * ) blen_object ); + PyList_Append( list, blen_object ); Py_DECREF( blen_object ); } base_iter = base_iter->next; } - return ( list ); + return list; } /*****************************************************************************/ @@ -1177,7 +1158,7 @@ static PyObject *Object_getIpo( BPy_Object * self ) return Ipo_CreatePyObject( ipo ); } -static PyObject *Object_getLocation( BPy_Object * self, PyObject * args ) +static PyObject *Object_getLocation( BPy_Object * self ) { PyObject *attr = Py_BuildValue( "fff", self->object->loc[0], @@ -1277,7 +1258,7 @@ static PyObject *Object_getParentBoneName( BPy_Object * self ) "Failed to get parent bone name" ) ); } -static PyObject *Object_getSize( BPy_Object * self, PyObject * args ) +static PyObject *Object_getSize( BPy_Object * self ) { PyObject *attr = Py_BuildValue( "fff", self->object->size[0], @@ -1350,7 +1331,6 @@ static PyObject *Object_getType( BPy_Object * self ) } } - static PyObject *Object_getBoundBox( BPy_Object * self ) { int i; @@ -1482,7 +1462,7 @@ static PyObject *Object_link( BPy_Object * self, PyObject * args ) } if( ArmatureObject_Check( py_data ) ) data = ( void * ) PyArmature_AsArmature((BPy_Armature*)py_data); - if( Camera_CheckPyObject( py_data ) ) + else if( Camera_CheckPyObject( py_data ) ) data = ( void * ) Camera_FromPyObject( py_data ); else if( Lamp_CheckPyObject( py_data ) ) data = ( void * ) Lamp_FromPyObject( py_data ); @@ -1823,10 +1803,10 @@ static PyObject *internal_makeParent(Object *parent, PyObject *py_child, return EXPP_incr_ret( Py_None ); } -static PyObject *Object_materialUsage( BPy_Object * self, PyObject * args ) +static PyObject *Object_materialUsage( void ) { - return ( EXPP_ReturnPyObjError( PyExc_NotImplementedError, - "materialUsage: not yet implemented" ) ); + return EXPP_ReturnPyObjError( PyExc_NotImplementedError, + "materialUsage: not yet implemented" ); } static PyObject *Object_setDeltaLocation( BPy_Object * self, PyObject * args ) @@ -2594,7 +2574,7 @@ static PyObject *Object_getEffects( BPy_Object * self ) eff = self->object->effect.first; while( eff ) { - PyList_Append( effect_list, EffectCreatePyObject( eff ) ); + PyList_Append( effect_list, EffectCreatePyObject( eff, self->object ) ); eff = eff->next; } return effect_list; @@ -2610,16 +2590,15 @@ PyObject *Object_CreatePyObject( struct Object * obj ) BPy_Object *blen_object; if( !obj ) - return EXPP_incr_ret( Py_None ); + Py_RETURN_NONE; blen_object = ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); - if( blen_object == NULL ) { - return ( NULL ); + if( blen_object ) { + blen_object->object = obj; + obj->id.us++; } - blen_object->object = obj; - obj->id.us++; return ( ( PyObject * ) blen_object ); } @@ -2778,11 +2757,9 @@ static PyObject *Object_getAttr( BPy_Object * obj, char *name ) } if( StringEqual( name, "parent" ) ) { if( object->parent ) - return ( Object_CreatePyObject( object->parent ) ); - else { - Py_INCREF( Py_None ); - return ( Py_None ); - } + return Object_CreatePyObject( object->parent ); + else + Py_RETURN_NONE; } if( StringEqual( name, "parentbonename" ) ) { if( object->parent && object->parsubstr[0] ) @@ -2794,7 +2771,7 @@ static PyObject *Object_getAttr( BPy_Object * obj, char *name ) } if( StringEqual( name, "track" ) ) - return ( Object_CreatePyObject( object->track ) ); + return Object_CreatePyObject( object->track ); if( StringEqual( name, "data" ) ) { PyObject *getdata, *tuple = PyTuple_New(0); @@ -2864,6 +2841,8 @@ static PyObject *Object_getAttr( BPy_Object * obj, char *name ) } if( StringEqual( name, "effects" ) ) return Object_getEffects( obj ); + if( StringEqual( name, "users" ) ) + return PyInt_FromLong( obj->object->id.us ); /* not an attribute, search the methods table */ return Py_FindMethod( BPy_Object_methods, ( PyObject * ) obj, name ); diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py index 7e2476173a9..8226e442c5d 100644 --- a/source/blender/python/api2_2x/doc/Object.py +++ b/source/blender/python/api2_2x/doc/Object.py @@ -4,6 +4,9 @@ The Blender.Object submodule B{New}: + - Objects now increment the Blender user count when they are created and + decremented it when they are destroyed. This means Python scripts can + keep the object "alive" if it is deleted in the Blender GUI. - L{Object.getData} now accepts two optional bool keyword argument to define (1) if the user wants the data object or just its name and (2) if a mesh object should use NMesh or Mesh. @@ -187,6 +190,8 @@ class Object: @ivar sel: The selection state of the object in the current scene, 1 is selected, 0 is unselected. @ivar effects: The list of particle effects associated with the object. (Read-only) @ivar parentbonename: The string name of the parent bone. + @ivar users: The number of users of the object. Read-only. + @type users: int """ def buildParts(): @@ -1233,4 +1238,4 @@ class Property: """ Get the type for this property. @rtype: string - """ \ No newline at end of file + """