Index: Armature.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/python/api2_2x/Armature.c,v
retrieving revision 1.18
diff -u -p -r1.18 Armature.c
--- Armature.c	7 Oct 2004 19:25:39 -0000	1.18
+++ Armature.c	4 Jan 2005 10:30:22 -0000
@@ -102,7 +102,7 @@ static int Armature_setAttr( BPy_Armatur
 			     PyObject * v );
 static int Armature_compare( BPy_Armature * a1, BPy_Armature * a2 );
 static PyObject *Armature_repr( BPy_Armature * armature );
-static int doesBoneName_exist( char *name, bArmature * arm );
+static Bone *testBoneNameInArmature( bArmature * arm, char *name );
 
 //---------------- Python TypeArmature structure definition:-----------
 PyTypeObject Armature_Type = {
@@ -150,27 +150,27 @@ PyObject *Armature_Init( void )
 //----------------------Blender Armature Module internal callbacks----
 
 //------------------append_childrenToList-----------------------------------
-static void append_childrenToList( Bone * parent, PyObject * listbones )
-{
+static void append_childrenToList( bArmature *armature, Bone * parent, PyObject * listbones )
+{		/* Recursive; finds all bones that are children of given bone */
 	Bone *child = NULL;
 
 	//append children 
 	for( child = parent->childbase.first; child; child = child->next ) {
-		PyList_Append( listbones, Bone_CreatePyObject( child ) );
+		PyList_Append( listbones, Bone_CreatePyObject( armature, child ) );
 		if( child->childbase.first ) {	//has children?
-			append_childrenToList( child, listbones );
+			append_childrenToList( armature, child, listbones );
 		}
 	}
 }
 
 //------------------unique_BoneName----------------------------
 static void unique_BoneName( char *name, bArmature * arm )
-{
+{		/* Ensures a name is unique by adding .number */
 	char tempname[64];
 	int number;
 	char *dot;
 
-	if( doesBoneName_exist( name, arm ) ) {
+	if( testBoneNameInArmature( arm, name ) ) {
 		/*      Strip off the suffix */
 		dot = strchr( name, '.' );
 		if( dot )
@@ -178,7 +178,7 @@ static void unique_BoneName( char *name,
 
 		for( number = 1; number <= 999; number++ ) {
 			sprintf( tempname, "%s.%03d", name, number );
-			if( !doesBoneName_exist( tempname, arm ) ) {
+			if( !testBoneNameInArmature( arm, tempname ) ) {
 				strcpy( name, tempname );
 				return;
 			}
@@ -186,27 +186,9 @@ static void unique_BoneName( char *name,
 	}
 }
 
-//------------------doesBoneName_exist----------------------------
-static int doesBoneName_exist( char *name, bArmature * arm )
-{
-	Bone *parent = NULL;
-	Bone *child = NULL;
-
-	for( parent = arm->bonebase.first; parent; parent = parent->next ) {
-		if( !strcmp( name, parent->name ) )
-			return 1;
-		for( child = parent->childbase.first; child;
-		     child = child->next ) {
-			if( !strcmp( name, child->name ) )
-				return 1;
-		}
-	}
-	return 0;
-}
-
 //------------------testChildInChildbase--------------------------
 static int testChildInChildbase( Bone * bone, Bone * test )
-{
+{		/* Recursive; tests if a bone is among the descendants of another */
 	Bone *child;
 	for( child = bone->childbase.first; child; child = child->next ) {
 		if( child == test ) {
@@ -224,7 +206,7 @@ static int testChildInChildbase( Bone * 
 
 //------------------testBoneInArmature-----------------------------
 static int testBoneInArmature( bArmature * arm, Bone * test )
-{
+{		/* Checks if a bone is in an armature */
 	Bone *root;
 	for( root = arm->bonebase.first; root; root = root->next ) {
 		if( root == test ) {
@@ -242,7 +224,7 @@ static int testBoneInArmature( bArmature
 
 //-----------------testChildNameInChildbase--------------------------
 static Bone *testChildNameInChildbase( Bone * bone, char *name )
-{
+{		/* Recursive; test if a bone name is among the descendants of a bone */
 	Bone *child;
 	Bone *test;
 	for( child = bone->childbase.first; child; child = child->next ) {
@@ -261,7 +243,7 @@ static Bone *testChildNameInChildbase( B
 
 //----------------testBoneNameInArmature----------------------------
 static Bone *testBoneNameInArmature( bArmature * arm, char *name )
-{
+{		/* Full recursive check of a bone name existing in an armature */
 	Bone *bone;
 	Bone *test;
 	for( bone = arm->bonebase.first; bone; bone = bone->next ) {
@@ -526,9 +508,9 @@ static PyObject *Armature_getBones( BPy_
 	//append root bones
 	for( parent = self->armature->bonebase.first; parent;
 	     parent = parent->next ) {
-		PyList_Append( listbones, Bone_CreatePyObject( parent ) );
+		PyList_Append( listbones, Bone_CreatePyObject( self->armature, parent ) );
 		if( parent->childbase.first ) {	//has children?
-			append_childrenToList( parent, listbones );
+			append_childrenToList( self->armature, parent, listbones );
 		}
 	}
 
@@ -542,53 +524,33 @@ static PyObject *Armature_addBone( BPy_A
 	float M_boneObjectspace[4][4];
 	float iM_parentRest[4][4];
 	Bone *blen_bone;
-	char *parent_str = "";
 	Bone *parent;
 
 	if( !PyArg_ParseTuple( args, "O!", &Bone_Type, &py_bone ) )
 		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 						"expected bone object argument (or nothing)" ) );
 
-	if( py_bone->bone != NULL )
+	if( py_bone->armature != NULL )
 		return EXPP_ReturnPyObjError( PyExc_TypeError,
 					      "this bone has already been linked to an armature" );
 
+	blen_bone=py_bone->bone;
+	parent=blen_bone->parent;
+
 	//check to see if we can parent this bone if it will be attempted 
         //otherwise exit
-	if( !BLI_streq( py_bone->parent, parent_str ) ) {	//parenting being attempted
-		//get parent if exists in this armature
-		parent = testBoneNameInArmature( self->armature,
-						 py_bone->parent );
-		if( !parent ) {	//could find the parent's name
+	if ( parent != NULL ) {
+		if ( ! testBoneInArmature(self->armature, parent) ) {
 			return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-							"cannot find parent's name in armature - check to see if name of parent is correct" ) );
+							"cannot find parent bone in armature" ) );
 		}
-	} else {		//no parent for this bone
-		parent = NULL;
 	}
 
-	//create a bone struct
-	blen_bone = ( Bone * ) MEM_callocN( sizeof( Bone ), "DefaultBone" );
-
-	//set the bone struct pointer
-	py_bone->bone = blen_bone;
-	//update the bonestruct data from py data
-	if( !updateBoneData( py_bone, parent ) )
-		return EXPP_ReturnPyObjError( PyExc_AttributeError,
-					      "bone struct empty" );
-
 	//make sure the name is unique for this armature
-	unique_BoneName( py_bone->bone->name, self->armature );
+	unique_BoneName( blen_bone->name, self->armature );
 
 	//if bone has a parent....      
-	if( py_bone->bone->parent ) {
-
-		//then check to see if parent has been added to the armature - bone loop test
-		if( !testBoneInArmature
-		    ( self->armature, py_bone->bone->parent ) )
-			return ( EXPP_ReturnPyObjError
-				 ( PyExc_TypeError,
-				   "cannot parent to a bone not yet added to armature!" ) );
+	if( parent ) {
 
 		//add to parent's childbase
 		BLI_addtail( &py_bone->bone->parent->childbase,
@@ -607,6 +569,13 @@ static PyObject *Armature_addBone( BPy_A
 
 	} else			//no parent....
 		BLI_addtail( &self->armature->bonebase, py_bone->bone );
+	py_bone->armature = self->armature;
+
+	if ( py_bone->parent ) {
+		// We have a full in-armature connection, remove the python one
+		Py_DECREF(py_bone->parent);
+		py_bone->parent = NULL;
+	}
 
 	//rebuild_bone_parent_matrix(py_bone->bone);
 
Index: Bone.c
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/python/api2_2x/Bone.c,v
retrieving revision 1.22
diff -u -p -r1.22 Bone.c
--- Bone.c	7 Oct 2004 19:25:39 -0000	1.22
+++ Bone.c	4 Jan 2005 10:30:22 -0000
@@ -231,127 +231,26 @@ PyObject *Bone_Init( void )
 
 //--------------- Bone module internal callbacks-----------------
 
-//--------------- updatePyBone------------------------------------
-int updatePyBone( BPy_Bone * self )
-{
-	int x, y;
-	char *parent_str = "";
-
-	if( !self->bone ) {
-		//nothing to update - not linked
-		return 0;
-	} else {
-		BLI_strncpy( self->name, self->bone->name,
-			     strlen( self->bone->name ) + 1 );
-		self->roll = self->bone->roll;
-		self->flag = self->bone->flag;
-		self->boneclass = self->bone->boneclass;
-		self->dist = self->bone->dist;
-		self->weight = self->bone->weight;
-
-		if( self->bone->parent ) {
-			self->parent =
-				BLI_strncpy( self->parent,
-					     self->bone->parent->name,
-					     strlen( self->bone->parent->
-						     name ) + 1 );
-		} else {
-			self->parent =
-				BLI_strncpy( self->parent, parent_str,
-					     strlen( parent_str ) + 1 );
-		}
-
-		for( x = 0; x < 3; x++ ) {
-			self->head->vec[x] = self->bone->head[x];
-			self->tail->vec[x] = self->bone->tail[x];
-			self->loc->vec[x] = self->bone->loc[x];
-			self->dloc->vec[x] = self->bone->dloc[x];
-			self->size->vec[x] = self->bone->size[x];
-			self->dsize->vec[x] = self->bone->dsize[x];
-		}
-		for( x = 0; x < 4; x++ ) {
-			self->quat->quat[x] = self->bone->quat[x];
-			self->dquat->quat[x] = self->bone->dquat[x];
-		}
-		for( x = 0; x < 4; x++ ) {
-			for( y = 0; y < 4; y++ ) {
-				self->obmat->matrix[x][y] =
-					self->bone->obmat[x][y];
-				self->parmat->matrix[x][y] =
-					self->bone->parmat[x][y];
-				self->defmat->matrix[x][y] =
-					self->bone->defmat[x][y];
-				self->irestmat->matrix[x][y] =
-					self->bone->irestmat[x][y];
-				self->posemat->matrix[x][y] =
-					self->bone->posemat[x][y];
-			}
-		}
-		return 1;
+//--------------- testAncestor----------------------------------
+// checks if bone is an ancestor of test
+static int testAncestor( Bone * bone, BPy_Bone * test )
+{
+	// Python parents
+	while ( test->parent ) {
+		if ( test->bone==bone )
+			return 1;
+		else
+			test=(BPy_Bone*)test->parent;
 	}
-}
-
-//--------------- updateBoneData------------------------------------
-int updateBoneData( BPy_Bone * self, Bone * parent )
-{
-	//called from Armature.addBone()
-	int x, y;
-
-	//called in Armature.addBone() to update the Bone * data
-	if( !self->bone ) {
-		//nothing to update - not linked
-		return 0;
-	} else {
-		BLI_strncpy( self->bone->name, self->name,
-			     strlen( self->name ) + 1 );
-		self->bone->roll = self->roll;
-		self->bone->flag = self->flag;
-		self->bone->boneclass = self->boneclass;
-		self->bone->dist = self->dist;
-		self->bone->weight = self->weight;
-		self->bone->parent = parent;	//parent will be checked from self->parent string in addBone()
-
-		for( x = 0; x < 3; x++ ) {
-			self->bone->head[x] = self->head->vec[x];
-			self->bone->tail[x] = self->tail->vec[x];
-			self->bone->loc[x] = self->loc->vec[x];
-			self->bone->dloc[x] = self->dloc->vec[x];
-			self->bone->size[x] = self->size->vec[x];
-			self->bone->dsize[x] = self->dsize->vec[x];
-		}
-		for( x = 0; x < 4; x++ ) {
-			self->bone->quat[x] = self->quat->quat[x];
-			self->bone->dquat[x] = self->dquat->quat[x];
-		}
-		for( x = 0; x < 4; x++ ) {
-			for( y = 0; y < 4; y++ ) {
-				self->bone->obmat[x][y] =
-					self->obmat->matrix[x][y];
-				self->bone->parmat[x][y] =
-					self->parmat->matrix[x][y];
-				self->bone->defmat[x][y] =
-					self->defmat->matrix[x][y];
-				self->bone->irestmat[x][y] =
-					self->irestmat->matrix[x][y];
-				self->bone->posemat[x][y] =
-					self->posemat->matrix[x][y];
-			}
-		}
+	if ( test->bone == bone )
 		return 1;
-	}
-}
-
-//--------------- testChildbase----------------------------------
-static int testChildbase( Bone * bone, Bone * test )
-{
-	Bone *child;
-
-	for( child = bone->childbase.first; child; child = child->next ) {
-		if( child == test ) {
+	// Armature parents
+	Bone *test2 = test->bone;
+	while ( test2->parent ) {
+		if ( test2->parent==bone )
 			return 1;
-		}
-		if( child->childbase.first != NULL )
-			testChildbase( child, test );
+		else
+			test2=test2->parent;
 	}
 
 	return 0;
@@ -361,56 +260,55 @@ static int testChildbase( Bone * bone, B
 static PyObject *returnBoneclassEnum( int value )
 {
 	char *str;
-	str = PyMem_Malloc( 32 + 1 );
 
 	switch ( value ) {
 	case 0:
-		BLI_strncpy( str, "SKINNABLE", 32 );
+		str="SKINNABLE";
 		break;
 	case 1:
-		BLI_strncpy( str, "UNSKINNABLE", 32 );
+		str="UNSKINNABLE";
 		break;
 	case 2:
-		BLI_strncpy( str, "HEAD", 32 );
+		str="HEAD";
 		break;
 	case 3:
-		BLI_strncpy( str, "NECK", 32 );
+		str="NECK";
 		break;
 	case 4:
-		BLI_strncpy( str, "BACK", 32 );
+		str="BACK";
 		break;
 	case 5:
-		BLI_strncpy( str, "SHOULDER", 32 );
+		str="SHOULDER";
 		break;
 	case 6:
-		BLI_strncpy( str, "ARM", 32 );
+		str="ARM";
 		break;
 	case 7:
-		BLI_strncpy( str, "HAND", 32 );
+		str="HAND";
 		break;
 	case 8:
-		BLI_strncpy( str, "FINGER", 32 );
+		str="FINGER";
 		break;
 	case 9:
-		BLI_strncpy( str, "THUMB", 32 );
+		str="THUMB";
 		break;
 	case 10:
-		BLI_strncpy( str, "PELVIS", 32 );
+		str="PELVIS";
 		break;
 	case 11:
-		BLI_strncpy( str, "LEG", 32 );
+		str="LEG";
 		break;
 	case 12:
-		BLI_strncpy( str, "FOOT", 32 );
+		str="FOOT";
 		break;
 	case 13:
-		BLI_strncpy( str, "TOE", 32 );
+		str="TOE";
 		break;
 	case 14:
-		BLI_strncpy( str, "TENTACLE", 32 );
+		str="TENTACLE";
 		break;
 	default:
-		BLI_strncpy( str, "SKINNABLE", 32 );
+		str="SKINNABLE";
 		break;
 	}
 	return ( PyObject * ) PyString_FromString( str );
@@ -421,8 +319,11 @@ static PyObject *returnBoneclassEnum( in
 //--------------- dealloc------------------------------------------
 static void Bone_dealloc( BPy_Bone * self )
 {
-	PyMem_Free( self->name );
-	PyMem_Free( self->parent );
+	if ( self->armature==NULL ) {
+		// Never linked to an armature, destroy the bone
+		Py_XDECREF(self->parent);
+		MEM_freeN(self->bone);
+	}
 	PyObject_DEL( self );
 }
 
@@ -484,8 +385,7 @@ static int Bone_setAttr( BPy_Bone * self
 	valtuple = Py_BuildValue( "(O)", value );	/* the set* functions expect a tuple */
 
 	if( !valtuple )
-		return EXPP_ReturnIntError( PyExc_MemoryError,
-					    "BoneSetAttr: couldn't create tuple" );
+		return -1;
 
 	if( strcmp( name, "name" ) == 0 )
 		error = Bone_setName( self, valtuple );
@@ -494,7 +394,7 @@ static int Bone_setAttr( BPy_Bone * self
 
 		/* ... member with the given name was found */
 		return ( EXPP_ReturnIntError
-			 ( PyExc_KeyError, "attribute not found" ) );
+			 ( PyExc_AttributeError, "attribute not found" ) );
 	}
 
 	Py_DECREF( valtuple );
@@ -509,11 +409,8 @@ static int Bone_setAttr( BPy_Bone * self
 //--------------- repr---------------------------------------------
 static PyObject *Bone_repr( BPy_Bone * self )
 {
-	if( self->bone )
-		return PyString_FromFormat( "[Bone \"%s\"]",
-					    self->bone->name );
-	else
-		return PyString_FromString( "NULL" );
+	return PyString_FromFormat( "[Bone \"%s\"]",
+				    self->bone->name );
 }
 
 //--------------- compare------------------------------------------
@@ -524,7 +421,7 @@ static int Bone_compare( BPy_Bone * a, B
 }
 
 //--------------- Bone_CreatePyObject---------------------------------
-PyObject *Bone_CreatePyObject( struct Bone * bone )
+PyObject *Bone_CreatePyObject( bArmature *armature, struct Bone * bone )
 {
 	BPy_Bone *blen_bone;
 
@@ -533,52 +430,9 @@ PyObject *Bone_CreatePyObject( struct Bo
 	//set the all important Bone flag
 	blen_bone->bone = bone;
 
-	//allocate space for python vars
-	blen_bone->name = PyMem_Malloc( 32 + 1 );
-	blen_bone->parent = PyMem_Malloc( 32 + 1 );
-	blen_bone->head =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	blen_bone->tail =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	blen_bone->loc =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	blen_bone->dloc =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	blen_bone->size =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	blen_bone->dsize =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	blen_bone->quat =
-		( QuaternionObject * )
-		newQuaternionObject( PyMem_Malloc( 4 * sizeof( float ) ) );
-	blen_bone->dquat =
-		( QuaternionObject * )
-		newQuaternionObject( PyMem_Malloc( 4 * sizeof( float ) ) );
-	blen_bone->obmat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-	blen_bone->parmat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-	blen_bone->defmat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-	blen_bone->irestmat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-	blen_bone->posemat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-
-	if( !updatePyBone( blen_bone ) )
-		return EXPP_ReturnPyObjError( PyExc_AttributeError,
-					      "bone struct empty" );
+	//this isn't a newly created Python bone
+	blen_bone->armature = armature;
+	blen_bone->parent = NULL;
 
 	return ( ( PyObject * ) blen_bone );
 }
@@ -594,14 +448,9 @@ struct Bone *Bone_FromPyObject( PyObject
 {
 	BPy_Bone *blen_obj;
 
+	assert(Bone_CheckPyObject(py_obj));
 	blen_obj = ( BPy_Bone * ) py_obj;
-	if( !( ( BPy_Bone * ) py_obj )->bone ) {	//test to see if linked to armature
-		//use python vars
-		return NULL;
-	} else {
-		//use bone datastruct
-		return ( blen_obj->bone );
-	}
+	return ( blen_obj->bone );
 }
 
 //--------------- Python Bone Module methods------------------------
@@ -610,87 +459,59 @@ struct Bone *Bone_FromPyObject( PyObject
 static PyObject *M_Bone_New( PyObject * self, PyObject * args )
 {
 	char *name_str = "BoneName";
-	char *parent_str = "";
-	BPy_Bone *py_bone = NULL;	/* for Bone Data object wrapper in Python */
+	BPy_Bone *py_bone;
+	Bone *bone;
+	int x, y;
 
 	if( !PyArg_ParseTuple( args, "|s", &name_str ) )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-						"expected string or empty argument" ) );
+		return NULL;
 
 	//create python bone
 	py_bone = ( BPy_Bone * ) PyObject_NEW( BPy_Bone, &Bone_Type );
 
-	//allocate space for python vars
-	py_bone->name = PyMem_Malloc( 32 + 1 );
-	py_bone->parent = PyMem_Malloc( 32 + 1 );
-	py_bone->head =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	py_bone->tail =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	py_bone->loc =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	py_bone->dloc =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	py_bone->size =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	py_bone->dsize =
-		( VectorObject * )
-		newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 );
-	py_bone->quat =
-		( QuaternionObject * )
-		newQuaternionObject( PyMem_Malloc( 4 * sizeof( float ) ) );
-	py_bone->dquat =
-		( QuaternionObject * )
-		newQuaternionObject( PyMem_Malloc( 4 * sizeof( float ) ) );
-	py_bone->obmat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-	py_bone->parmat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-	py_bone->defmat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-	py_bone->irestmat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-	py_bone->posemat =
-		( MatrixObject * )
-		newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
+	//create blender bone
+	py_bone->bone = bone = ( Bone * ) MEM_callocN( sizeof( Bone ), "DefaultBone" );
+
+	py_bone->parent = NULL;
+	py_bone->armature = NULL;
 
 	//default py values
-	BLI_strncpy( py_bone->name, name_str, strlen( name_str ) + 1 );
-	BLI_strncpy( py_bone->parent, parent_str, strlen( parent_str ) + 1 );
-	py_bone->roll = 0.0f;
-	py_bone->flag = 32;
-	py_bone->boneclass = BONE_SKINNABLE;
-	py_bone->dist = 1.0f;
-	py_bone->weight = 1.0f;
-	Vector_Zero( py_bone->head );
-	Vector_Zero( py_bone->loc );
-	Vector_Zero( py_bone->dloc );
-	Vector_Zero( py_bone->size );
-	Vector_Zero( py_bone->dsize );
-	Quaternion_Identity( py_bone->quat );
-	Quaternion_Identity( py_bone->dquat );
-	Matrix_Identity( py_bone->obmat );
-	Matrix_Identity( py_bone->parmat );
-	Matrix_Identity( py_bone->defmat );
-	Matrix_Identity( py_bone->irestmat );
-	Matrix_Identity( py_bone->posemat );
+	BLI_strncpy( py_bone->bone->name, name_str, sizeof(py_bone->bone->name) );
+	bone->flag = 32;
+	bone->boneclass = BONE_SKINNABLE;
+	bone->dist = 1.0f;
+	bone->weight = 1.0f;
+	bone->roll = 0.0f;
+	for ( x = 0; x < 3; x++ ) {
+		bone->head[x] = 0;
+		bone->loc[x] = 0;
+		bone->dloc[x] = 0;
+		bone->size[x] = 0;
+		bone->dsize[x] = 0;
+	}
+	// Quaternion identity: 1,0,0,0
+	for ( x = 1; x < 4; x++ ) {
+		bone->quat[x] = 0.0f;
+		bone->dquat[x] = 0.0f;
+	}
+	bone->quat[0] = 1.0f;
+	bone->dquat[0] = 1.0f;
+	// Matrix identity: 0 for all except row=column which are 1
+	for ( x = 0; x < 4; x++ ) {
+		for ( y = 0; y < 4; y++ ) {
+			float v = x==y?1.0f:0.0f;
+			bone->obmat[x][y] = v;
+			bone->parmat[x][y] = v;
+			bone->defmat[x][y] = v;
+			bone->irestmat[x][y] = v;
+			bone->posemat[x][y] = v;
+		}
+	}
 
 	//default tail of 2,0,0
-	py_bone->tail->vec[0] = 2.0f;
-	py_bone->tail->vec[1] = 0.0f;
-	py_bone->tail->vec[2] = 0.0f;
-
-	//set the datapointer to null (unlinked)
-	py_bone->bone = NULL;
+	bone->tail[0] = 2.0f;
+	bone->tail[1] = 0.0f;
+	bone->tail[2] = 0.0f;
 
 	return ( PyObject * ) py_bone;
 }
@@ -700,243 +521,75 @@ static PyObject *M_Bone_New( PyObject * 
 //--------------- BPy_Bone.getName()--------------------------------
 static PyObject *Bone_getName( BPy_Bone * self )
 {
-	PyObject *attr = NULL;
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		attr = PyString_FromString( self->name );
-	} else {
-		//use bone datastruct
-		attr = PyString_FromString( self->bone->name );
-	}
-	if( attr )
-		return attr;
-
-	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"couldn't get Bone.name attribute" ) );
+	return PyString_FromString( self->bone->name );
 }
 
 //--------------- BPy_Bone.getRoll()---------------------------------
 static PyObject *Bone_getRoll( BPy_Bone * self )
 {
-	PyObject *attr = NULL;
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		attr = Py_BuildValue( "f", self->roll );
-	} else {
-		//use bone datastruct
-		attr = Py_BuildValue( "f", self->bone->roll );
-	}
-	if( attr )
-		return attr;
-
-	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"couldn't get Bone.roll attribute" ) );
+	return PyFloat_FromDouble( self->bone->roll );
 }
 
 //--------------- BPy_Bone.getWeight()---------------------------------
 static PyObject *Bone_getWeight( BPy_Bone * self )
 {
-	PyObject *attr = NULL;
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		attr = Py_BuildValue( "f", self->weight );
-	} else {
-		//use bone datastruct
-		attr = Py_BuildValue( "f", self->bone->weight );
-	}
-	if( attr )
-		return attr;
-
-	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"couldn't get Bone.weight attribute" ) );
+	return PyFloat_FromDouble( self->bone->weight );
 }
 
 //--------------- BPy_Bone.getHead()----------------------------------
 static PyObject *Bone_getHead( BPy_Bone * self )
 {
-	PyObject *attr = NULL;
-	float *vec;
-	int x;
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		vec = PyMem_Malloc( 3 * sizeof( float ) );
-		for( x = 0; x < 3; x++ )
-			vec[x] = self->head->vec[x];
-		attr = ( PyObject * ) newVectorObject( vec, 3 );
-	} else {
-		//use bone datastruct
-		attr = newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ),
-					3 );
-		( ( VectorObject * ) attr )->vec[0] = self->bone->head[0];
-		( ( VectorObject * ) attr )->vec[1] = self->bone->head[1];
-		( ( VectorObject * ) attr )->vec[2] = self->bone->head[2];
-	}
-	if( attr )
-		return attr;
-
-	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"couldn't get Bone.head attribute" ) );
+	// A quick read of the new* functions in mathutils showed that
+	// they COPY their argument for initialization, and go for identity
+	// if the argument is NULL. Don't allocate, do pass nice pointer.
+	return newVectorObject( self->bone->head, 3 );
 }
 
 //--------------- BPy_Bone.getTail()---------------------------------
 static PyObject *Bone_getTail( BPy_Bone * self )
 {
-	PyObject *attr = NULL;
-	float *vec;
-	int x;
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		vec = PyMem_Malloc( 3 * sizeof( float ) );
-		for( x = 0; x < 3; x++ )
-			vec[x] = self->tail->vec[x];
-		attr = ( PyObject * ) newVectorObject( vec, 3 );
-	} else {
-		//use bone datastruct
-		attr = newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ),
-					3 );
-		( ( VectorObject * ) attr )->vec[0] = self->bone->tail[0];
-		( ( VectorObject * ) attr )->vec[1] = self->bone->tail[1];
-		( ( VectorObject * ) attr )->vec[2] = self->bone->tail[2];
-	}
-	if( attr )
-		return attr;
-
-	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"couldn't get Bone.tail attribute" ) );
+	return newVectorObject( self->bone->tail, 3 );
 }
 
 //--------------- BPy_Bone.getLoc()---------------------------------
 static PyObject *Bone_getLoc( BPy_Bone * self )
 {
-	PyObject *attr = NULL;
-	float *vec;
-	int x;
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		vec = PyMem_Malloc( 3 * sizeof( float ) );
-		for( x = 0; x < 3; x++ )
-			vec[x] = self->loc->vec[x];
-		attr = ( PyObject * ) newVectorObject( vec, 3 );
-	} else {
-		//use bone datastruct
-		attr = newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ),
-					3 );
-		( ( VectorObject * ) attr )->vec[0] = self->bone->loc[0];
-		( ( VectorObject * ) attr )->vec[1] = self->bone->loc[1];
-		( ( VectorObject * ) attr )->vec[2] = self->bone->loc[2];
-	}
-	if( attr )
-		return attr;
-
-	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"couldn't get Bone.loc attribute" ) );
+	return newVectorObject( self->bone->loc, 3 );
 }
 
 //--------------- BPy_Bone.getSize()-----------------------------
 static PyObject *Bone_getSize( BPy_Bone * self )
 {
-	PyObject *attr = NULL;
-	float *vec;
-	int x;
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		vec = PyMem_Malloc( 3 * sizeof( float ) );
-		for( x = 0; x < 3; x++ )
-			vec[x] = self->size->vec[x];
-		attr = ( PyObject * ) newVectorObject( vec, 3 );
-	} else {
-		//use bone datastruct
-		attr = newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ),
-					3 );
-		( ( VectorObject * ) attr )->vec[0] = self->bone->size[0];
-		( ( VectorObject * ) attr )->vec[1] = self->bone->size[1];
-		( ( VectorObject * ) attr )->vec[2] = self->bone->size[2];
-	}
-	if( attr )
-		return attr;
-
-	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"couldn't get Bone.size attribute" ) );
+	return newVectorObject( self->bone->size, 3 );
 }
 
 //--------------- BPy_Bone.getQuat()--------------------------------
 static PyObject *Bone_getQuat( BPy_Bone * self )
 {
-	PyObject *attr = NULL;
-	float *quat;
-	int x;
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars - p.s. - you must return a copy or else
-		//python will trash the internal var
-		quat = PyMem_Malloc( 4 * sizeof( float ) );
-		for( x = 0; x < 4; x++ )
-			quat[x] = self->quat->quat[x];
-		attr = ( PyObject * ) newQuaternionObject( quat );
-	} else {
-		//use bone datastruct
-		attr = newQuaternionObject( PyMem_Malloc
-					    ( 4 * sizeof( float ) ) );
-		( ( QuaternionObject * ) attr )->quat[0] = self->bone->quat[0];
-		( ( QuaternionObject * ) attr )->quat[1] = self->bone->quat[1];
-		( ( QuaternionObject * ) attr )->quat[2] = self->bone->quat[2];
-		( ( QuaternionObject * ) attr )->quat[3] = self->bone->quat[3];
-	}
-
-	return attr;
+	return newQuaternionObject( self->bone->quat );
 }
 
 //--------------- BPy_Bone.hasParent()---------------------------
 static PyObject *Bone_hasParent( BPy_Bone * self )
 {
-	char *parent_str = "";
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		if( BLI_streq( self->parent, parent_str ) ) {
-			Py_INCREF( Py_False );
-			return Py_False;
-		} else {
-			Py_INCREF( Py_True );
-			return Py_True;
-		}
+	if( self->bone->parent ) {
+		Py_INCREF( Py_True );
+		return Py_True;
 	} else {
-		//use bone datastruct
-		if( self->bone->parent ) {
-			Py_INCREF( Py_True );
-			return Py_True;
-		} else {
-			Py_INCREF( Py_False );
-			return Py_False;
-		}
+		Py_INCREF( Py_False );
+		return Py_False;
 	}
 }
 
 //--------------- BPy_Bone.getParent()------------------------------
 static PyObject *Bone_getParent( BPy_Bone * self )
 {
-	char *parent_str = "";
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		if( BLI_streq( self->parent, parent_str ) ) {
-			return EXPP_incr_ret( Py_None );
-		} else {
-			return PyString_FromString( self->parent );
-		}
+	if( self->parent ) {
+		return EXPP_incr_ret( self->parent );
+	} else if( self->armature && self->bone->parent ) {
+		return Bone_CreatePyObject( self->armature, self->bone->parent );
 	} else {
-		//use bone datastruct
-		if( self->bone->parent ) {
-			return Bone_CreatePyObject( self->bone->parent );
-		} else {
-			return EXPP_incr_ret( Py_None );
-		}
+		return EXPP_incr_ret( Py_None );
 	}
 }
 
@@ -948,26 +601,31 @@ static PyObject *Bone_getChildren( BPy_B
 	PyObject *listbones = NULL;
 	int i;
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		return EXPP_incr_ret( Py_None );
-	} else {
-		//use bone datastruct
-		current = self->bone->childbase.first;
-		for( ; current; current = current->next )
-			totbones++;
-
-		/* Create a list with a bone wrapper for each bone */
-		current = self->bone->childbase.first;
-		listbones = PyList_New( totbones );
-		for( i = 0; i < totbones; i++ ) {
-			assert( current );
-			PyList_SetItem( listbones, i,
-					Bone_CreatePyObject( current ) );
-			current = current->next;
-		}
-		return listbones;
+	if ( self->armature == NULL ) {
+		return ( EXPP_ReturnPyObjError( PyExc_ValueError,
+						"child bone tracking not implemented outside armatures" ) );
+	}
+	// FIXME - children list will behave funny when bones not linked
+	// to armatures are involved. 
+	// Current behaviour: ONLY children in the same armature are in
+	// childbase and will show. Unadded bones never have valid
+	// children lists.
+	totbones = BLI_countlist ( &self->bone->childbase );
+
+	if ( totbones ) {
+		assert( self->armature );
+	}
+
+	/* Create a list with a bone wrapper for each bone */
+	current = self->bone->childbase.first;
+	listbones = PyList_New( totbones );
+	for( i = 0; i < totbones; i++ ) {
+		assert( current );
+		PyList_SetItem( listbones, i,
+				Bone_CreatePyObject( self->armature, current ) );
+		current = current->next;
 	}
+	return listbones;
 }
 
 //--------------- BPy_Bone.setName()---------------------------------
@@ -976,17 +634,9 @@ static PyObject *Bone_setName( BPy_Bone 
 	char *name;
 
 	if( !PyArg_ParseTuple( args, "s", &name ) )
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_AttributeError,
-			   "expected string argument" ) );
+		return NULL;
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		BLI_strncpy( self->name, name, strlen( name ) + 1 );
-	} else {
-		//use bone datastruct
-		BLI_strncpy( self->bone->name, name, strlen( name ) + 1 );
-	}
+	BLI_strncpy( self->bone->name, name, sizeof(self->bone->name) );
 	return EXPP_incr_ret( Py_None );
 }
 
@@ -996,16 +646,10 @@ PyObject *Bone_setRoll( BPy_Bone * self,
 	float roll;
 
 	if( !PyArg_ParseTuple( args, "f", &roll ) )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-						"expected float argument" ) );
+		return NULL;
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		self->roll = roll;
-	} else {
-		//use bone datastruct
-		self->bone->roll = roll;
-	}
+	//use bone datastruct
+	self->bone->roll = roll;
 	return EXPP_incr_ret( Py_None );
 }
 
@@ -1021,20 +665,13 @@ static PyObject *Bone_setHead( BPy_Bone 
 		status = PyArg_ParseTuple( args, "(fff)", &f1, &f2, &f3 );
 
 	if( !status )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
+		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 						"expected 3 (or a list of 3) float arguments" ) );
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		self->head->vec[0] = f1;
-		self->head->vec[1] = f2;
-		self->head->vec[2] = f3;
-	} else {
-		//use bone datastruct
-		self->bone->head[0] = f1;
-		self->bone->head[1] = f2;
-		self->bone->head[2] = f3;
-	}
+	self->bone->head[0] = f1;
+	self->bone->head[1] = f2;
+	self->bone->head[2] = f3;
+
 	return EXPP_incr_ret( Py_None );
 }
 
@@ -1050,20 +687,14 @@ static PyObject *Bone_setTail( BPy_Bone 
 		status = PyArg_ParseTuple( args, "(fff)", &f1, &f2, &f3 );
 
 	if( !status )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
+		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 						"expected 3 (or a list of 3) float arguments" ) );
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		self->tail->vec[0] = f1;
-		self->tail->vec[1] = f2;
-		self->tail->vec[2] = f3;
-	} else {
-		//use bone datastruct
-		self->bone->tail[0] = f1;
-		self->bone->tail[1] = f2;
-		self->bone->tail[2] = f3;
-	}
+	//use bone datastruct
+	self->bone->tail[0] = f1;
+	self->bone->tail[1] = f2;
+	self->bone->tail[2] = f3;
+
 	return EXPP_incr_ret( Py_None );
 }
 
@@ -1079,20 +710,14 @@ static PyObject *Bone_setLoc( BPy_Bone *
 		status = PyArg_ParseTuple( args, "(fff)", &f1, &f2, &f3 );
 
 	if( !status )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
+		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 						"expected 3 (or a list of 3) float arguments" ) );
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		self->loc->vec[0] = f1;
-		self->loc->vec[1] = f2;
-		self->loc->vec[2] = f3;
-	} else {
-		//use bone datastruct
-		self->bone->loc[0] = f1;
-		self->bone->loc[1] = f2;
-		self->bone->loc[2] = f3;
-	}
+	//use bone datastruct
+	self->bone->loc[0] = f1;
+	self->bone->loc[1] = f2;
+	self->bone->loc[2] = f3;
+
 	return EXPP_incr_ret( Py_None );
 }
 
@@ -1108,20 +733,14 @@ static PyObject *Bone_setSize( BPy_Bone 
 		status = PyArg_ParseTuple( args, "(fff)", &f1, &f2, &f3 );
 
 	if( !status )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
+		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 						"expected 3 (or a list of 3) float arguments" ) );
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		self->size->vec[0] = f1;
-		self->size->vec[1] = f2;
-		self->size->vec[2] = f3;
-	} else {
-		//use bone datastruct
-		self->bone->size[0] = f1;
-		self->bone->size[1] = f2;
-		self->bone->size[2] = f3;
-	}
+	//use bone datastruct
+	self->bone->size[0] = f1;
+	self->bone->size[1] = f2;
+	self->bone->size[2] = f3;
+
 	return EXPP_incr_ret( Py_None );
 }
 
@@ -1130,8 +749,6 @@ static PyObject *Bone_setQuat( BPy_Bone 
 {
 	float f1, f2, f3, f4;
 	PyObject *argument;
-	QuaternionObject *quatOb;
-	int status;
 
 	if( !PyArg_ParseTuple( args, "O", &argument ) )
 		return ( EXPP_ReturnPyObjError
@@ -1139,34 +756,22 @@ static PyObject *Bone_setQuat( BPy_Bone 
 			   "expected quaternion or float list" ) );
 
 	if( QuaternionObject_Check( argument ) ) {
-		status = PyArg_ParseTuple( args, "O!", &quaternion_Type,
-					   &quatOb );
+		QuaternionObject *quatOb = (QuaternionObject*)argument;
 		f1 = quatOb->quat[0];
 		f2 = quatOb->quat[1];
 		f3 = quatOb->quat[2];
 		f4 = quatOb->quat[3];
 	} else {
-		status = PyArg_ParseTuple( args, "(ffff)", &f1, &f2, &f3,
-					   &f4 );
+		if (!PyArg_ParseTuple( args, "(ffff)", &f1, &f2, &f3, &f4 ))
+			return NULL;
 	}
 
-	if( !status )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-						"unable to parse argument" ) );
+	//use bone datastruct
+	self->bone->quat[0] = f1;
+	self->bone->quat[1] = f2;
+	self->bone->quat[2] = f3;
+	self->bone->quat[3] = f4;
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		self->quat->quat[0] = f1;
-		self->quat->quat[1] = f2;
-		self->quat->quat[2] = f3;
-		self->quat->quat[3] = f4;
-	} else {
-		//use bone datastruct
-		self->bone->quat[0] = f1;
-		self->bone->quat[1] = f2;
-		self->bone->quat[2] = f3;
-		self->bone->quat[3] = f4;
-	}
 	return EXPP_incr_ret( Py_None );
 }
 
@@ -1177,38 +782,31 @@ static PyObject *Bone_setParent( BPy_Bon
 	float M_boneObjectspace[4][4];
 	float iM_parentRest[4][4];
 
-	if( !PyArg_ParseTuple( args, "O", &py_bone ) )
-		return ( EXPP_ReturnPyObjError
-			 ( PyExc_TypeError,
-			   "expected bone object argument" ) );
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		BLI_strncpy( self->parent, py_bone->name,
-			     strlen( py_bone->name ) + 1 );
-	} else {
-		//use bone datastruct
-		if( !py_bone->bone )
-			return ( EXPP_ReturnPyObjError
-				 ( PyExc_TypeError,
-				   "Parent bone must be linked to armature first!" ) );
-
-		if( py_bone->bone == self->bone )
-			return ( EXPP_ReturnPyObjError
-				 ( PyExc_AttributeError,
-				   "Cannot parent to self" ) );
+	if( !PyArg_ParseTuple( args, "O!", &Bone_Type, &py_bone ) )
+		return NULL;
 
-		//test to see if were creating an illegal loop by parenting to child
-		if( testChildbase( self->bone, py_bone->bone ) )
-			return ( EXPP_ReturnPyObjError
-				 ( PyExc_AttributeError,
-				   "Cannot parent to child" ) );
+	if( py_bone->bone == self->bone )
+		return ( EXPP_ReturnPyObjError
+			 ( PyExc_ValueError,
+			   "Cannot parent to self" ) );
 
-		//set the parent of self - in this case 
-                //we are changing the parenting after this bone
-		//has been linked in it's armature
-		if( self->bone->parent ) {	//we are parenting something previously parented
+	//test to see if were creating an illegal loop by parenting to child
+	if( testAncestor( self->bone, py_bone ) )
+		return ( EXPP_ReturnPyObjError
+			 ( PyExc_ValueError,
+			   "Cannot parent to child" ) );
 
+	if ( self->armature && py_bone->armature!=self->armature )
+		return ( EXPP_ReturnPyObjError
+			 ( PyExc_ValueError,
+			   "Cannot move bone out of armature" ) );
+	// The reason we cannot move a bone out of an armature is that we can't
+	// know if there are python references to child bones, in which case those
+	// must make the same move.
+
+	// Remove old parent link
+	if ( self->armature ) {
+		if ( self->bone->parent ) {
 			//remove the childbase link from the parent bone
 			BLI_remlink( &self->bone->parent->childbase,
 				     self->bone );
@@ -1219,34 +817,33 @@ static PyObject *Bone_setParent( BPy_Bon
 			Mat4MulVecfl( M_boneObjectspace, self->bone->head );
 			Mat4MulVecfl( M_boneObjectspace, self->bone->tail );
 
-			//add to the childbase of new parent
-			BLI_addtail( &py_bone->bone->childbase, self->bone );
-
-			//transform bone according to new parent
-			get_objectspace_bone_matrix( py_bone->bone,
-						     M_boneObjectspace, 0, 0 );
-			Mat4Invert( iM_parentRest, M_boneObjectspace );
-			Mat4MulVecfl( iM_parentRest, self->bone->head );
-			Mat4MulVecfl( iM_parentRest, self->bone->tail );
-
-			//set parent
-			self->bone->parent = py_bone->bone;
-
-		} else {	//not previously parented
-
-			//add to the childbase of new parent
-			BLI_addtail( &py_bone->bone->childbase, self->bone );
+		} else {
+			// no bone parent, but we're in an armature. remove root bone.
+			BLI_remlink( &self->armature->bonebase, self->bone );
+		}
 
-			//transform bone according to new parent
-			get_objectspace_bone_matrix( py_bone->bone,
-						     M_boneObjectspace, 0, 0 );
-			Mat4Invert( iM_parentRest, M_boneObjectspace );
-			Mat4MulVecfl( iM_parentRest, self->bone->head );
-			Mat4MulVecfl( iM_parentRest, self->bone->tail );
+		//add to the childbase of new parent
+		BLI_addtail( &py_bone->bone->childbase, self->bone );
 
-			self->bone->parent = py_bone->bone;
+		//transform bone according to new parent
+		get_objectspace_bone_matrix( py_bone->bone,
+					     M_boneObjectspace, 0, 0 );
+		Mat4Invert( iM_parentRest, M_boneObjectspace );
+		Mat4MulVecfl( iM_parentRest, self->bone->head );
+		Mat4MulVecfl( iM_parentRest, self->bone->tail );
+	} else {
+		if ( self->parent ) {
+			// Remove any Python bone parent
+			Py_DECREF (self->parent);
+			self->parent = NULL;
 		}
+		// link new python parent
+		Py_INCREF (py_bone);
+		self->parent = (PyObject*)py_bone;
 	}
+
+	self->bone->parent = py_bone->bone;
+
 	return EXPP_incr_ret( Py_None );
 }
 
@@ -1256,209 +853,105 @@ static PyObject *Bone_setWeight( BPy_Bon
 	float weight;
 
 	if( !PyArg_ParseTuple( args, "f", &weight ) )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-						"expected float argument" ) );
+		return NULL;
+
+	self->bone->weight = weight;
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		self->weight = weight;
-	} else {
-		//use bone datastruct
-		self->bone->weight = weight;
-	}
 	return EXPP_incr_ret( Py_None );
 }
 
 //--------------- BPy_Bone.clearParent()--------------------------
 static PyObject *Bone_clearParent( BPy_Bone * self )
 {
-	bArmature *arm = NULL;
-	Bone *bone = NULL;
-	Bone *parent = NULL;
-	Bone *child = NULL;
-	Bone *childPrev = NULL;
-	int firstChild;
-	float M_boneObjectspace[4][4];
-	char *parent_str = "";
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		BLI_strncpy( self->parent, parent_str,
-			     strlen( parent_str ) + 1 );
-	} else {
-		//use bone datastruct
-		if( self->bone->parent == NULL )
-			return EXPP_incr_ret( Py_None );
+	Bone *parent = self->bone->parent;
 
-		//get parent and remove link
-		parent = self->bone->parent;
-		self->bone->parent = NULL;
+	if( self->bone->parent == NULL )
+		return EXPP_incr_ret( Py_None );
 
+	if ( self->armature ) {
 		//remove the childbase link from the parent bone
-		firstChild = 1;
-		for( child = parent->childbase.first; child;
-		     child = child->next ) {
-			if( child == self->bone && firstChild ) {
-				parent->childbase.first = child->next;
-				child->next = NULL;
-				break;
-			}
-			if( child == self->bone && !firstChild ) {
-				childPrev->next = child->next;
-				child->next = NULL;
-				break;
-			}
-			firstChild = 0;
-			childPrev = child;
-		}
+		BLI_remlink( &parent->childbase, self->bone );
 
 		//now get rid of the parent transformation
+		float M_boneObjectspace[4][4];
 		get_objectspace_bone_matrix( parent, M_boneObjectspace, 0, 0 );
 
 		//transformation of local bone
 		Mat4MulVecfl( M_boneObjectspace, self->bone->head );
 		Mat4MulVecfl( M_boneObjectspace, self->bone->tail );
 
-		//get the root bone
-		while( parent->parent != NULL ) {
-			parent = parent->parent;
-		}
-
 		//add unlinked bone to the bonebase of the armature
-		for( arm = G.main->armature.first; arm; arm = arm->id.next ) {
-			for( bone = arm->bonebase.first; bone;
-			     bone = bone->next ) {
-				if( parent == bone ) {
-					//we found the correct armature - now add it as root bone
-					BLI_addtail( &arm->bonebase,
-						     self->bone );
-					break;
-				}
-			}
-		}
+		BLI_addtail( &self->armature->bonebase, self->bone );
+	} else if ( self->parent ) {
+		Py_DECREF(self->parent);
+		self->parent=NULL;
 	}
+
+	//remove parent references
+	self->bone->parent = NULL;
+
 	return EXPP_incr_ret( Py_None );
 }
 
 //--------------- BPy_Bone.clearChildren()------------------------
 static PyObject *Bone_clearChildren( BPy_Bone * self )
 {
-	Bone *root = NULL;
 	Bone *child = NULL;
-	bArmature *arm = NULL;
-	Bone *bone = NULL;
-	Bone *prev = NULL;
-	Bone *next = NULL;
 	float M_boneObjectspace[4][4];
-	int first;
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		return EXPP_incr_ret( Py_None );
-	} else {
-		//use bone datastruct
-		if( self->bone->childbase.first == NULL )
-			return EXPP_incr_ret( Py_None );
-
-		//is this bone a part of an armature....
-		//get root bone for testing
-		root = self->bone->parent;
-		if( root != NULL ) {
-			while( root->parent != NULL ) {
-				root = root->parent;
-			}
-		} else {
-			root = self->bone;
-		}
-		//test armatures for root bone
-		for( arm = G.main->armature.first; arm; arm = arm->id.next ) {
-			for( bone = arm->bonebase.first; bone;
-			     bone = bone->next ) {
-				if( bone == root )
-					break;
-			}
-			if( bone == root )
-				break;
-		}
-
-		if( arm == NULL )
-			return ( EXPP_ReturnPyObjError
-				 ( PyExc_RuntimeError,
-				   "couldn't find armature that contains this bone" ) );
+	if( self->armature == NULL ) {
+		// Not linked to an armature, can't track children
+		return ( EXPP_ReturnPyObjError
+		 	( PyExc_ValueError,
+		   	"can't remove children from a bone not in an armature" ) );
+	}
 
-		//now get rid of the parent transformation
-		get_objectspace_bone_matrix( self->bone, M_boneObjectspace, 0,
-					     0 );
+	if( self->bone->childbase.first == NULL ) {
+		// No children (that we know of - unadded bones are screwed)
+		return EXPP_incr_ret( Py_None );
+	}
 
-		//set children as root
-		first = 1;
-		for( child = self->bone->childbase.first; child; child = next ) {
-			//undo transformation of local bone
-			Mat4MulVecfl( M_boneObjectspace, child->head );
-			Mat4MulVecfl( M_boneObjectspace, child->tail );
-
-			//set next pointers to NULL
-			if( first ) {
-				prev = child;
-				first = 0;
-			} else {
-				prev->next = NULL;
-				prev = child;
-			}
-			next = child->next;
+	//now get rid of the parent transformation
+	get_objectspace_bone_matrix( self->bone, M_boneObjectspace, 0,
+				     0 );
+
+	//remove transformation and parenting from children
+	for( child = self->bone->childbase.first; child; child = child->next ) {
+		Mat4MulVecfl( M_boneObjectspace, child->head );
+		Mat4MulVecfl( M_boneObjectspace, child->tail );
+		child->parent = NULL;
+	}
 
-			//remove parenting and linking
-			child->parent = NULL;
-			BLI_remlink( &self->bone->childbase, child );
+	// Move the bones to the root of the armature
+	addlisttolist( &self->armature->bonebase, &self->bone->childbase );
 
-			//add as root
-			BLI_addtail( &arm->bonebase, child );
-		}
-	}
-	Py_INCREF( Py_None );
-	return Py_None;
+	return EXPP_incr_ret( Py_None );
 }
 
 //--------------- BPy_Bone.hide()-----------------------------------
 static PyObject *Bone_hide( BPy_Bone * self )
 {
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		return EXPP_ReturnPyObjError( PyExc_TypeError,
-					      "link bone to armature before attempting to hide/unhide" );
-	} else {
-		//use bone datastruct
-		if( !( self->bone->flag & BONE_HIDDEN ) )
-			self->bone->flag |= BONE_HIDDEN;
-	}
+	if( !( self->bone->flag & BONE_HIDDEN ) )
+		self->bone->flag |= BONE_HIDDEN;
 	return EXPP_incr_ret( Py_None );
 }
 
 //--------------- BPy_Bone.unhide()-------------------------------
 static PyObject *Bone_unhide( BPy_Bone * self )
 {
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		return EXPP_ReturnPyObjError( PyExc_TypeError,
-					      "link bone to armature before attempting to hide/unhide" );
-	} else {
-		//use bone datastruct
-		if( self->bone->flag & BONE_HIDDEN )
-			self->bone->flag &= ~BONE_HIDDEN;
-	}
+	//use bone datastruct
+	if( self->bone->flag & BONE_HIDDEN )
+		self->bone->flag &= ~BONE_HIDDEN;
 	return EXPP_incr_ret( Py_None );
 }
 
 //--------------- BPy_Bone.setPose()-------------------------------
 static PyObject *Bone_setPose( BPy_Bone * self, PyObject * args )
 {
-	Bone *root = NULL;
 	bPoseChannel *chan = NULL;
 	bPoseChannel *setChan = NULL;
 	bPoseChannel *test = NULL;
 	Object *object = NULL;
-	bArmature *arm = NULL;
-	Bone *bone = NULL;
 	PyObject *flaglist = NULL;
 	PyObject *item = NULL;
 	BPy_Action *py_action = NULL;
@@ -1466,8 +959,7 @@ static PyObject *Bone_setPose( BPy_Bone 
 	int flagValue = 0;
 	int makeCurve = 1;
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
+	if( !self->armature ) {	//test to see if linked to armature
 		return EXPP_ReturnPyObjError( PyExc_TypeError,
 					      "cannot set pose unless bone is linked to armature" );
 	} else {
@@ -1476,8 +968,11 @@ static PyObject *Bone_setPose( BPy_Bone 
 		    ( args, "O!|O!", &PyList_Type, &flaglist, &Action_Type,
 		      &py_action ) )
 			return ( EXPP_ReturnPyObjError
-				 ( PyExc_AttributeError,
+				 ( PyExc_TypeError,
 				   "expected list of flags and optional action" ) );
+		// Personally I think requiring that to be a list is unnecessary.
+		// And then it turns out to be a bitmask, too.
+		// FIXME - what about py_actions with no action? can't happen?
 
 		for( x = 0; x < PyList_Size( flaglist ); x++ ) {
 			item = PyList_GetItem( flaglist, x );
@@ -1490,43 +985,19 @@ static PyObject *Bone_setPose( BPy_Bone 
 			}
 		}
 
-		//is this bone a part of an armature....
-		//get root bone for testing
-		root = self->bone->parent;
-		if( root != NULL ) {
-			while( root->parent != NULL ) {
-				root = root->parent;
-			}
-		} else {
-			root = self->bone;
-		}
-		//test armatures for root bone
-		for( arm = G.main->armature.first; arm; arm = arm->id.next ) {
-			for( bone = arm->bonebase.first; bone;
-			     bone = bone->next ) {
-				if( bone == root )
-					break;
-			}
-			if( bone == root )
-				break;
-		}
-		if( arm == NULL )
-			return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-							"bone must belong to an armature to set it's pose!" ) );
-
 		//find if armature is object linked....
 		for( object = G.main->object.first; object;
 		     object = object->id.next ) {
-			if( object->data == arm ) {
+			if( object->data == self->armature ) {
 				break;
 			}
 		}
 
 		if( object == NULL )
-			return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
+			return ( EXPP_ReturnPyObjError( PyExc_ValueError,
 							"armature must be linked to an object to set a pose!" ) );
 
-		//set the active action as this one
+		//set the active action as this one - XXX side effect
 		if( py_action != NULL ) {
 			if( py_action->action != NULL ) {
 				object->action = py_action->action;
@@ -1536,7 +1007,7 @@ static PyObject *Bone_setPose( BPy_Bone 
 		if( !object->pose )
 			object->pose = MEM_callocN( sizeof( bPose ), "Pose" );
 
-		//if bone does have a channel create one
+		//if bone does not have a channel create one
 		verify_pose_channel( object->pose, self->bone->name );
 		//create temp Pose Channel
 		chan = MEM_callocN( sizeof( bPoseChannel ), "PoseChannel" );
@@ -1559,8 +1030,10 @@ static PyObject *Bone_setPose( BPy_Bone 
 			//test if posechannel is already in action
 			for( test = object->action->chanbase.first; test;
 			     test = test->next ) {
-				if( test == setChan )
+				if( test == setChan ) {
 					makeCurve = 0;	//already there
+					break;
+				}
 			}
 		}
 
@@ -1603,20 +1076,8 @@ static PyObject *Bone_setPose( BPy_Bone 
 //--------------- BPy_Bone.getBoneclass()--------------------------
 static PyObject *Bone_getBoneclass( BPy_Bone * self )
 {
-	PyObject *attr = NULL;
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		attr = returnBoneclassEnum( self->boneclass );
-	} else {
-		//use bone datastruct
-		attr = returnBoneclassEnum( self->bone->boneclass );
-	}
-	if( attr )
-		return attr;
-
-	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"couldn't get Bone.Boneclass attribute" ) );
+	//use bone datastruct
+	return returnBoneclassEnum( self->bone->boneclass );
 }
 
 //--------------- BPy_Bone.setBoneclass()---------------------------
@@ -1628,94 +1089,57 @@ static PyObject *Bone_setBoneclass( BPy_
 		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
 						"expected enum argument" ) );
 
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		self->boneclass = boneclass;
-	} else {
-		//use bone datastruct
-		self->bone->boneclass = boneclass;
-	}
+	//use bone datastruct
+	self->bone->boneclass = boneclass;
 	return EXPP_incr_ret( Py_None );
 }
 
 //--------------- BPy_Bone.hasIK()-------------------------------
 static PyObject *Bone_hasIK( BPy_Bone * self )
 {
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		if( self->flag & BONE_IK_TOPARENT ) {
-			Py_INCREF( Py_True );
-			return Py_True;
-		} else {
-			Py_INCREF( Py_False );
-			return Py_False;
-		}
+	//use bone datastruct
+	if( self->bone->flag & BONE_IK_TOPARENT ) {
+		Py_INCREF( Py_True );
+		return Py_True;
 	} else {
-		//use bone datastruct
-		if( self->bone->flag & BONE_IK_TOPARENT ) {
-			Py_INCREF( Py_True );
-			return Py_True;
-		} else {
-			Py_INCREF( Py_False );
-			return Py_False;
-		}
+		Py_INCREF( Py_False );
+		return Py_False;
 	}
-	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-					"couldn't get Bone.Boneclass attribute" ) );
 }
 
 //--------------- BPy_Bone.getRestMatrix()-------------------------
 static PyObject *Bone_getRestMatrix( BPy_Bone * self, PyObject * args )
 {
-	char *local = "worldspace";
 	char *bonespace = "bonespace";
 	char *worldspace = "worldspace";
-	PyObject *matrix;
+	char *local = worldspace;
+	float matrix[4][4];
 	float delta[3];
 	float root[3];
 	float p_root[3];
 
 	if( !PyArg_ParseTuple( args, "|s", &local ) )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-						"expected string" ) );
+		return NULL;
 
 	if( !BLI_streq( local, bonespace ) && !BLI_streq( local, worldspace ) )
-		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
+		return ( EXPP_ReturnPyObjError( PyExc_ValueError,
 						"expected 'bonespace' or 'worldspace'" ) );
 
-	matrix = newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 );
-
-	if( !self->bone ) {	//test to see if linked to armature
-		//use python vars
-		if( BLI_streq( local, worldspace ) ) {
-			VecSubf( delta, self->tail->vec, self->head->vec );
-			make_boneMatrixvr( *( ( MatrixObject * ) matrix )->
-					   matrix, delta, self->roll );
-		} else if( BLI_streq( local, bonespace ) ) {
-			return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-							"bone not yet linked to an armature....'" ) );
-		}
-	} else {
-		//use bone datastruct
-		if( BLI_streq( local, worldspace ) ) {
-			get_objectspace_bone_matrix( self->bone,
-						     *( ( MatrixObject * )
-							matrix )->matrix, 1,
-						     1 );
-		} else if( BLI_streq( local, bonespace ) ) {
-			VecSubf( delta, self->bone->tail, self->bone->head );
-			make_boneMatrixvr( *( ( MatrixObject * ) matrix )->
-					   matrix, delta, self->bone->roll );
-			if( self->bone->parent ) {
-				get_bone_root_pos( self->bone, root, 1 );
-				get_bone_root_pos( self->bone->parent, p_root,
-						   1 );
-				VecSubf( delta, root, p_root );
-				VECCOPY( ( ( MatrixObject * ) matrix )->
-					 matrix[3], delta );
-			}
+	if( BLI_streq( local, worldspace ) ) {
+		get_objectspace_bone_matrix( self->bone, matrix, 1, 1 );
+	} else if( BLI_streq( local, bonespace ) ) {
+		VecSubf( delta, self->bone->tail, self->bone->head );
+		make_boneMatrixvr( matrix, delta, self->bone->roll );
+		if( self->bone->parent ) {
+			// Department of confusing APIs. WHAT format is returned,
+			// and what format can you set?
+			get_bone_root_pos( self->bone, root, 1 );
+			get_bone_root_pos( self->bone->parent, p_root,
+					   1 );
+			VecSubf( delta, root, p_root );
+			VECCOPY( matrix[3], delta );
 		}
 	}
 
-	return matrix;
+	return newMatrixObject( *matrix, 4, 4 );
 }
Index: Bone.h
===================================================================
RCS file: /cvsroot/bf-blender/blender/source/blender/python/api2_2x/Bone.h,v
retrieving revision 1.6
diff -u -p -r1.6 Bone.h
--- Bone.h	25 Sep 2004 20:30:39 -0000	1.6
+++ Bone.h	4 Jan 2005 10:30:22 -0000
@@ -42,36 +42,22 @@
 //--------------------------Python BPy_Bone structure definition.-------
 typedef struct {
 	PyObject_HEAD
-		//reference to data if bone is linked to an armature
-	Bone * bone;
-	//list of vars that define the boneclass
-	char *name;
-	char *parent;
-	float roll;
-	int flag;
-	int boneclass;
-	float dist;
-	float weight;
-	VectorObject *head;
-	VectorObject *tail;
-	VectorObject *loc;
-	VectorObject *dloc;
-	VectorObject *size;
-	VectorObject *dsize;
-	QuaternionObject *quat;
-	QuaternionObject *dquat;
-	MatrixObject *obmat;
-	MatrixObject *parmat;
-	MatrixObject *defmat;
-	MatrixObject *irestmat;
-	MatrixObject *posemat;
+	Bone * bone;		// never NULL
+	bArmature * armature;	// NULL iff bone not yet in any armature
+	// If armature is NULL, use this Python field for parent reference
+	// parent field in bone WILL be filled in too
+	// bones IN armatures do not know about child bones NOT in armature
+	//  neither do bones not in armature; parent works, children doesn't.
+	//  this matches the old behaviour of the children field
+	PyObject * parent;
+	// Also, bone transformations are performed at addBone time,
+	// so set/clearParent should only do them if armature is set
 } BPy_Bone;
 
 //------------------------------visible prototypes----------------------
-PyObject *Bone_CreatePyObject( struct Bone *obj );
+PyObject *Bone_CreatePyObject( bArmature * armature,  struct Bone *obj );
 int Bone_CheckPyObject( PyObject * py_obj );
 Bone *Bone_FromPyObject( PyObject * py_obj );
 PyObject *Bone_Init( void );
-int updateBoneData( BPy_Bone * self, Bone * parent );
 
 #endif
