diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d92ec5d31b8..4c8a9042f64 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -294,13 +294,6 @@ void unlink_object(Object *ob) if ELEM(obt->type, OB_CURVE, OB_FONT) { cu= obt->data; - /* this test is for a bug in the Python API with Object.New(): - * objects can be created without any obdata; when deleted, - * a segfault occurs since obt->data == NULL */ - if (!cu) { - printf ("ERROR: found curve object with no obdata!\n"); - break; - } if(cu->bevobj==ob) { cu->bevobj= NULL; diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index 9c529bd8652..01bc08436e6 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -790,6 +790,8 @@ PyObject *M_Object_New( PyObject * self_unused, PyObject * args ) char *str_type; char *name = NULL; Object *add_only_object(int type, char *name); + PyObject *py_object; + BPy_Object *blen_object; if( !PyArg_ParseTuple( args, "s|s", &str_type, &name ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -835,7 +837,15 @@ PyObject *M_Object_New( PyObject * self_unused, PyObject * args ) object->id.us = 0; /* Create a Python object from it. */ - return Object_CreatePyObject( object ); + py_object = Object_CreatePyObject( object ); + blen_object = (BPy_Object *)py_object; + + /* store the real object type in the PyObject, treat this as an Empty + * until it has some obdata */ + blen_object->realtype = object->type; + object->type = OB_EMPTY; + + return py_object; } /*****************************************************************************/ @@ -1370,7 +1380,13 @@ static PyObject *Object_getTracked( BPy_Object * self ) static PyObject *Object_getType( BPy_Object * self ) { char *str; - switch ( self->object->type ) { + int type = self->object->type; + + /* if object not yet linked to data, return the stored type */ + if( self->realtype != OB_EMPTY ) + type = self->realtype; + + switch ( type ) { case OB_ARMATURE: str = "Armature"; break; @@ -1408,6 +1424,7 @@ static PyObject *Object_getType( BPy_Object * self ) str = "unknown"; break; } + return PyString_FromString( str ); } @@ -1568,6 +1585,13 @@ static PyObject *Object_link( BPy_Object * self, PyObject * args ) id = ( ID * ) data; obj_id = MAKE_ID2( id->name[0], id->name[1] ); + /* if the object object has not been linked to real data before, we + * can now let it assume its real type */ + if( self->realtype != OB_EMPTY ) { + self->object->type = self->realtype; + self->realtype = OB_EMPTY; + } + ok = 1; switch ( obj_id ) { case ID_AR: @@ -3123,10 +3147,10 @@ Object *GetObjectByName( char *name ) /*****************************************************************************/ static void Object_dealloc( BPy_Object * self ) { - if( self->object->data ) - self->object->id.us--; - else + if( self->realtype != OB_EMPTY ) free_libblock_us( &G.main->object, self->object ); + else + self->object->id.us--; #if 0 /* this will adjust the ID and if zero delete the object */ free_libblock_us( &G.main->object, self->object ); diff --git a/source/blender/python/api2_2x/Object.h b/source/blender/python/api2_2x/Object.h index 79783db619f..5d9951c13c3 100644 --- a/source/blender/python/api2_2x/Object.h +++ b/source/blender/python/api2_2x/Object.h @@ -48,9 +48,9 @@ extern PyTypeObject Object_Type; typedef struct { PyObject_HEAD struct Object *object; + short realtype; } BPy_Object; - PyObject *Object_Init( void ); PyObject *Object_CreatePyObject( struct Object *obj ); Object *Object_FromPyObject( PyObject * py_obj ); diff --git a/source/blender/python/api2_2x/Scene.c b/source/blender/python/api2_2x/Scene.c index eb204619f2a..7502c292753 100644 --- a/source/blender/python/api2_2x/Scene.c +++ b/source/blender/python/api2_2x/Scene.c @@ -809,8 +809,16 @@ static PyObject *Scene_link( BPy_Scene * self, PyObject * args ) return EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't allocate new Base for object" ); + /* if the object has not yet been linked to object data, then + * set the real type before we try creating data */ + + if( bpy_obj->realtype != OB_EMPTY ) { + object->type = bpy_obj->realtype; + bpy_obj->realtype = OB_EMPTY; + } + /* check if this object has obdata, case not, try to create it */ - + if( !object->data && ( object->type != OB_EMPTY ) ) EXPP_add_obdata( object ); /* returns -1 on error, defined in Object.c */ diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py index 46b65f43b5e..595f9c7c7c7 100644 --- a/source/blender/python/api2_2x/doc/Object.py +++ b/source/blender/python/api2_2x/doc/Object.py @@ -108,14 +108,14 @@ Example:: def New (type, name='type'): """ - Creates a new Object. + Creates a new Object. Deprecated; instead use Scene.objects.new(). @type type: string @param type: The Object type: 'Armature', 'Camera', 'Curve', 'Lamp', 'Lattice', 'Mball', 'Mesh', 'Surf' or 'Empty'. @type name: string @param name: The name of the object. By default, the name will be the same as the object type. - If the name is alredy in use, this new object will have a number at the end of the name. + If the name is already in use, this new object will have a number at the end of the name. @return: The created Object. I{B{Example:}} @@ -131,6 +131,11 @@ def New (type, name='type'): scene.link(object) Blender.Redraw() + @Note: if an object is created but is not linked to object data, and the + object is not linked to a scene, it will be deleted when the Python + object is deallocated. This is because Blender does not allow objects + to exist without object data unless they are Empty objects. Scene.link() + will automatically create object data for an object if it has none. """ def Get (name = None):