[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [12521] trunk/blender/source/blender/src/ editarmature.c: Patch #7760: X-Axis-Mirror support for 'make bone parent'

Joshua Leung aligorith at gmail.com
Thu Nov 8 09:06:51 CET 2007


Revision: 12521
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=12521
Author:   aligorith
Date:     2007-11-08 09:06:50 +0100 (Thu, 08 Nov 2007)

Log Message:
-----------
Patch #7760: X-Axis-Mirror support for 'make bone parent'

This patch by Teppo K?\195?\164ns?\195?\164l?\195?\164 (teppoka) makes parenting bones with Ctrl-P support the X-Axis-Mirror option for Armatures. It will cause the mirror-bone of the selected bone to also get parented. i.e. if "bone.R" was selected and being parented, "bone.L" would also get parented.

I've made an addition to this patch, which means that if the bone that acts as the parent also has a mirror-bone (i.e. when parenting "lowerArm.L" to "upperArm.L", "lowerArm.R" gets parented to "upperArm.R"). Otherwise, they both get parented to the same parent bone (i.e. a parent bone that doesn't belong on either side such as "upperSpine")

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

Modified: trunk/blender/source/blender/src/editarmature.c
===================================================================
--- trunk/blender/source/blender/src/editarmature.c	2007-11-08 03:31:52 UTC (rev 12520)
+++ trunk/blender/source/blender/src/editarmature.c	2007-11-08 08:06:50 UTC (rev 12521)
@@ -1884,12 +1884,68 @@
 	BIF_undo_push("Reveal Bones");
 }
 
+/* check for null, before calling! */
+static void bone_connect_to_existing_parent(EditBone *bone)
+{
+	bone->flag |= BONE_CONNECTED;
+	VECCOPY(bone->head, bone->parent->tail);
+	bone->rad_head = bone->parent->rad_tail;
+}
+
+static void bone_connect_to_new_parent(EditBone *selbone, EditBone *actbone, short mode)
+{
+	EditBone *ebone;
+	float offset[3];
+	
+	if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
+		selbone->parent->flag &= ~(BONE_TIPSEL);
+	
+	/* make actbone the parent of selbone */
+	selbone->parent= actbone;
+	
+	/* in actbone tree we cannot have a loop */
+	for (ebone= actbone->parent; ebone; ebone= ebone->parent) {
+		if (ebone->parent==selbone) {
+			ebone->parent= NULL;
+			ebone->flag &= ~BONE_CONNECTED;
+		}
+	}
+	
+	if (mode == 1) {	
+		/* Connected: Child bones will be moved to the parent tip */
+		selbone->flag |= BONE_CONNECTED;
+		VecSubf(offset, actbone->tail, selbone->head);
+		
+		VECCOPY(selbone->head, actbone->tail);
+		selbone->rad_head= actbone->rad_tail;
+		
+		VecAddf(selbone->tail, selbone->tail, offset);
+		
+		/* offset for all its children */
+		for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
+			EditBone *par;
+			
+			for (par= ebone->parent; par; par= par->parent) {
+				if (par==selbone) {
+					VecAddf(ebone->head, ebone->head, offset);
+					VecAddf(ebone->tail, ebone->tail, offset);
+					break;
+				}
+			}
+		}
+	}
+	else {
+		/* Offset: Child bones will retain their distance from the parent tip */
+		selbone->flag &= ~BONE_CONNECTED;
+	}
+}
+
 void make_bone_parent(void)
 {
 	bArmature *arm= G.obedit->data;
 	EditBone *actbone, *ebone, *selbone;
+	EditBone *flipbone, *flippar;
 	short allchildbones= 0, foundselbone= 0;
-	float offset[3];
 	short val;
 	
 	/* find active bone to parent to */
@@ -1931,59 +1987,40 @@
 		/* When only the active bone is selected, and it has a parent,
 		 * connect it to the parent, as that is the only possible outcome. 
 		 */
-		actbone->flag |= BONE_CONNECTED;
-		VECCOPY(actbone->head, actbone->parent->tail);
-		actbone->rad_head= actbone->parent->rad_tail;
+		bone_connect_to_existing_parent(actbone);
+		
+		if (arm->flag & ARM_MIRROR_EDIT) {
+			flipbone = armature_bone_get_mirrored(actbone);
+			if (flipbone)
+				bone_connect_to_existing_parent(flipbone);
+		}
 	}
 	else {
 		/* loop through all editbones, parenting all selected bones to the active bone */
 		for (selbone = G.edbo.first; selbone; selbone=selbone->next) {
 			if (arm->layer & selbone->layer) {
 				if ((selbone->flag & BONE_SELECTED) && (selbone!=actbone)) {
-					/* if selbone had a parent we clear parent tip */
-					if (selbone->parent && (selbone->flag & BONE_CONNECTED))
-						selbone->parent->flag &= ~(BONE_TIPSEL);
+					/* parent selbone to actbone */
+					bone_connect_to_new_parent(selbone, actbone, val);
 					
-					/* make actbone the parent of selbone */
-					selbone->parent= actbone;
-					
-					/* in actbone tree we cannot have a loop */
-					for (ebone= actbone->parent; ebone; ebone= ebone->parent) {
-						if (ebone->parent==selbone) {
-							ebone->parent= NULL;
-							ebone->flag &= ~BONE_CONNECTED;
-						}
-					}
-					
-					if (val == 1) {	
-						/* Connected: Child bones will be moved to the parent tip */
-						selbone->flag |= BONE_CONNECTED;
-						VecSubf(offset, actbone->tail, selbone->head);
+					if (arm->flag & ARM_MIRROR_EDIT) {
+						/* - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone 
+						 *	(i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
+						 *	This is useful for arm-chains, for example parenting lower arm to upper arm
+						 * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
+						 *	then just use actbone. Useful when doing upper arm to spine.
+						 */
+						flipbone = armature_bone_get_mirrored(selbone);
+						flippar = armature_bone_get_mirrored(actbone);
 						
-						VECCOPY(selbone->head, actbone->tail);
-						selbone->rad_head= actbone->rad_tail;
-						
-						VecAddf(selbone->tail, selbone->tail, offset);
-						
-						/* offset for all its children */
-						for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
-							EditBone *par;
-							
-							for (par= ebone->parent; par; par= par->parent) {
-								if (par==selbone) {
-									VecAddf(ebone->head, ebone->head, offset);
-									VecAddf(ebone->tail, ebone->tail, offset);
-									break;
-								}
-							}
+						if (flipbone) {
+							if (flippar)
+								bone_connect_to_new_parent(flipbone, flippar, val);
+							else
+								bone_connect_to_new_parent(flipbone, actbone, val);
 						}
 					}
-					else {
-						/* Offset: Child bones will retain their distance from the parent tip */
-						selbone->flag &= ~BONE_CONNECTED;
-					}
 				}
-				
 			}
 		}
 	}
@@ -3142,3 +3179,4 @@
 }
 
 
+





More information about the Bf-blender-cvs mailing list