[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [14786] trunk/blender/source/blender/src/ editarmature.c: Separating armatures should now be more stable than it was, but is still too unstable to enable for release.

Joshua Leung aligorith at gmail.com
Sun May 11 13:53:12 CEST 2008


Revision: 14786
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=14786
Author:   aligorith
Date:     2008-05-11 13:53:12 +0200 (Sun, 11 May 2008)

Log Message:
-----------
Separating armatures should now be more stable than it was, but is still too unstable to enable for release. So for now, the old warning stands. 

Modified Paths:
--------------
    trunk/blender/source/blender/src/editarmature.c

Modified: trunk/blender/source/blender/src/editarmature.c
===================================================================
--- trunk/blender/source/blender/src/editarmature.c	2008-05-11 11:34:39 UTC (rev 14785)
+++ trunk/blender/source/blender/src/editarmature.c	2008-05-11 11:53:12 UTC (rev 14786)
@@ -180,7 +180,7 @@
 		
 		/*	Add children if necessary */
 		if (curBone->childbase.first) 
-			make_boneList (list, &curBone->childbase, eBone);
+			make_boneList(list, &curBone->childbase, eBone);
 	}
 }
 
@@ -600,25 +600,24 @@
 						float delta[3];
 						
 						/* Get the premat */
-						VecSubf (delta, curbone->tail, curbone->head);
+						VecSubf(delta, curbone->tail, curbone->head);
 						vec_roll_to_mat3(delta, curbone->roll, temp);
 						
-						Mat4MulMat34 (premat, temp, mat);
+						Mat4MulMat34(premat, temp, mat);
 						
 						Mat4MulVecfl(mat, curbone->head);
 						Mat4MulVecfl(mat, curbone->tail);
 						
 						/* Get the postmat */
-						VecSubf (delta, curbone->tail, curbone->head);
+						VecSubf(delta, curbone->tail, curbone->head);
 						vec_roll_to_mat3(delta, curbone->roll, temp);
 						Mat4CpyMat3(postmat, temp);
 						
 						/* Find the roll */
-						Mat4Invert (imat, premat);
-						Mat4MulMat4 (difmat, postmat, imat);
+						Mat4Invert(imat, premat);
+						Mat4MulMat4(difmat, postmat, imat);
 						
 						curbone->roll -= atan2(difmat[2][0], difmat[2][2]);
-						
 					}
 					
 					/* Fix Constraints and Other Links to this Bone and Armature */
@@ -651,13 +650,16 @@
 }
 
 /* Helper function for armature separating - link fixing */
-static void separated_armature_fix_links(Object *origArm, Object *newArm, ListBase *edbo)
+static void separated_armature_fix_links(Object *origArm, Object *newArm)
 {
 	Object *ob;
-	bPoseChannel *pchan;
+	bPoseChannel *pchan, *pcha, *pchb;
 	bConstraint *con;
-	EditBone *ebo, *ebn;
+	ListBase *npchans;
 	
+	/* get reference to list of bones in new armature  */
+	npchans= &newArm->pose->chanbase;
+	
 	/* let's go through all objects in database */
 	for (ob= G.main->object.first; ob; ob= ob->id.next) {
 		/* do some object-type specific things */
@@ -675,27 +677,21 @@
 						for (ct= targets.first; ct; ct= ct->next) {
 							/* any targets which point to original armature are redirected to the new one only if:
 							 *	- the target isn't the original armature itself
-							 *	- the target is one of the bones which were moved into newArm
+							 *	- the target is one that can be found in newArm
 							 */
 							if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
-								for (ebo=edbo->first, ebn=edbo->last; ebo && ebn; ebo=ebo->next, ebn=ebn->prev) {
+								for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
 									/* check if either one matches */
-									if ( (strcmp(ebo->name, ct->subtarget)==0) ||
-										 (strcmp(ebn->name, ct->subtarget)==0) )
+									if ( (strcmp(pcha->name, ct->subtarget)==0) ||
+										 (strcmp(pchb->name, ct->subtarget)==0) )
 									{
 										ct->tar= newArm;
-										printf("arm = '%s' pchan = '%s', ebo = '%s', YES \n", ob->id.name+2, pchan->name, ebo->name);
-										printf("arm = '%s' pchan = '%s', ebn = '%s', YES \n", ob->id.name+2, pchan->name, ebn->name);
 										break;
 									}
-									else {
-										printf("arm = '%s' pchan = '%s', ebo = '%s', NOT\n", ob->id.name+2, pchan->name, ebo->name);
-										printf("arm = '%s' pchan = '%s', ebn = '%s', NOT \n", ob->id.name+2, pchan->name, ebn->name);
-									}
 									
 									/* check if both ends have met (to stop checking) */
-									if (ebo == ebn) break;
-								}
+									if (pcha == pchb) break;
+								}								
 							}
 						}
 						
@@ -723,17 +719,17 @@
 						 *	- the target is one of the bones which were moved into newArm
 						 */
 						if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
-							for (ebo=edbo->first, ebn=edbo->last; ebo && ebn; ebo=ebo->next, ebn=ebn->prev) {
+							for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
 								/* check if either one matches */
-								if ( (strcmp(ebo->name, ct->subtarget)==0) ||
-									 (strcmp(ebn->name, ct->subtarget)==0) )
+								if ( (strcmp(pcha->name, ct->subtarget)==0) ||
+									 (strcmp(pchb->name, ct->subtarget)==0) )
 								{
 									ct->tar= newArm;
 									break;
 								}
 								
 								/* check if both ends have met (to stop checking) */
-								if (ebo == ebn) break;
+								if (pcha == pchb) break;
 							}
 						}
 					}
@@ -749,34 +745,86 @@
 			/* Is object parented to a bone of this src armature? */
 			if (ob->partype==PARBONE) {
 				/* bone name in object */
-				for (ebo=edbo->first, ebn=edbo->last; ebo && ebn; ebo=ebo->next, ebn=ebn->prev) {
+				for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
 					/* check if either one matches */
-					if ( (strcmp(ebo->name, ob->parsubstr)==0) ||
-						 (strcmp(ebn->name, ob->parsubstr)==0) )
+					if ( (strcmp(pcha->name, ob->parsubstr)==0) ||
+						 (strcmp(pchb->name, ob->parsubstr)==0) )
 					{
 						ob->parent= newArm;
 						break;
 					}
 					
 					/* check if both ends have met (to stop checking) */
-					if (ebo == ebn) break;
+					if (pcha == pchb) break;
 				}
 			}
 		}
 	}	
 }
 
+/* Helper function for armature separating - remove certain bones from the given armature 
+ *	sel: remove selected bones from the armature, otherwise the unselected bones are removed
+ */
+static void separate_armature_bones (Object *ob, short sel) 
+{
+	ListBase edbo = {NULL, NULL};
+	bArmature *arm= (bArmature *)ob->data;
+	bPoseChannel *pchan, *pchann;
+	EditBone *curbone;
+	
+	/* make local set of editbones to manipulate here */
+	make_boneList(&edbo, &arm->bonebase, NULL);
+	
+	/* go through pose-channels, checking if a bone should be removed */
+	for (pchan=ob->pose->chanbase.first; pchan; pchan=pchann) {
+		pchann= pchan->next;
+		curbone= editbone_name_exists(&edbo, pchan->name);
+		
+		/* check if bone needs to be removed */
+		if ( (sel && (curbone->flag & BONE_SELECTED)) ||
+			 (!sel && !(curbone->flag & BONE_SELECTED)) )
+		{
+			EditBone *ebo;
+			bPoseChannel *pchn;
+			
+			/* clear the bone->parent var of any bone that had this as its parent  */
+			for (ebo= edbo.first; ebo; ebo= ebo->next) {
+				if (ebo->parent == curbone) {
+					ebo->parent= NULL;
+					ebo->temp= NULL; /* this is needed to prevent random crashes with in editbones_to_armature */
+					ebo->flag &= ~BONE_CONNECTED;
+				}
+			}
+			
+			/* clear the pchan->parent var of any pchan that had this as its parent */
+			for (pchn= ob->pose->chanbase.first; pchn; pchn=pchn->next) {
+				if (pchn->parent == pchan)
+					pchn->parent= NULL;
+			}
+			
+			/* free any of the extra-data this pchan might have */
+			if (pchan->path) MEM_freeN(pchan->path);
+			free_constraints(&pchan->constraints);
+			
+			/* get rid of unneeded bone */
+			BLI_freelinkN(&edbo, curbone);
+			BLI_freelinkN(&ob->pose->chanbase, pchan);
+		}
+	}
+	
+	/* exit editmode (recalculates pchans too) */
+	editbones_to_armature(&edbo, ob);
+	BLI_freelistN(&edbo);
+}
+
 void separate_armature (void)
 {
-	EditBone *ebo, *ebn;
-	Object *oldob;
-	Base *base, *oldbase;
+	Object *oldob, *newob;
+	Base *base, *oldbase, *newbase;
 	bArmature *arm;
-	ListBase edbo = {NULL, NULL};
 	
-	// 31Mar08 - Aligorith:
-	//	this tool is currently not ready for production use, as it will still 
-	// 	crash in some cases, and also constraint relinking isn't working yet 
+	// 31 Mar 08 \ 11 May 08 - Aligorith:
+	// currently, this is still too unstable to be enabled for general consumption.
 	// remove the following two lines to test this tool... you have been warned!
 		okee("Not implemented (WIP)");
 		return;
@@ -788,77 +836,58 @@
 	
 	arm= G.obedit->data;
 	
-	/* we are going to trick everything as follows:
-	 * 1. duplicate base: this is the new one,  remember old pointer
-	 * 2. set aside all NOT selected bones
-	 * 3. load_editArmature(): this will be the new base
-	 * 4. freelist and restore old armature
+	/* we are going to do this as follows (unlike every other instance of separate):
+	 *	1. exit editmode for active armature/base. Take note of what this is. 
+	 *	2. duplicate base - BASACT is the new one now
+	 *	3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc
+	 *	4. fix constraint links
+	 *	5. make original armature active and enter editmode
 	 */
 	
-	/* only edit-base selected */
+	/* 1) only edit-base selected */
 	base= FIRSTBASE;
-	while(base) {
-		if(base->lay & G.vd->lay) {
-			if(base->object==G.obedit) base->flag |= 1;
+	for (base= FIRSTBASE; base; base= base->next) {
+		if (base->lay & G.vd->lay) {
+			if (base->object==G.obedit) base->flag |= 1;
 			else base->flag &= ~1;
 		}
-		base= base->next;
 	}
-
-	/* set aside: everything that is not selected */
-	for (ebo= G.edbo.first; ebo; ebo= ebn) {
-		ebn= ebo->next;
-		
-		/* remove from original, and move to duplicate if not-selected */
-		if ((ebo->flag & BONE_SELECTED)==0) {
-			EditBone *curbone;
-			
-			/* need to make sure children don't still refer to this only if they are selected
-			 * 	- potentially slow O(n*n) situation here... 
-			 */
-			for (curbone= G.edbo.first; curbone; curbone=curbone->next) {
-				if ((curbone->parent == ebo) && (curbone->flag & BONE_SELECTED)) {
-					curbone->parent= ebo->parent;
-					curbone->flag &= ~BONE_CONNECTED;
-				}
-			}
-			
-			BLI_remlink(&G.edbo, ebo);
-			BLI_addtail(&edbo, ebo); 
-		}
-	}
-
+	
+	/* 1) store starting settings and exit editmode */
 	oldob= G.obedit;
 	oldbase= BASACT;
-
-	adduplicate(1, 0); /* no transform and zero so do get a linked dupli */
 	
-	G.obedit= BASACT->object;	/* basact is set in adduplicate() */
+	load_editArmature();
+	free_editArmature();
 	
-	G.obedit->data= copy_armature(arm);
-	/* because new armature is a copy: reduce user count */
-	arm->id.us--;
+	/* 2) duplicate base */
+	adduplicate(1, USER_DUP_ARM); /* no transform and zero so do get a linked dupli */
 	
-	load_editArmature();
+	newbase= BASACT; /* basact is set in adduplicate() */
+	newob= newbase->object;		
+	newbase->flag &= ~SELECT;
 	
-	BASACT->flag &= ~SELECT;
 	
-	/* fix links before depsgraph flushes */ // err... or after?
-	printf("oldob = %p, obact = %p \n", oldob, G.obedit);
-	separated_armature_fix_links(oldob, G.obedit, &G.edbo);

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list