示例#1
0
/* 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
 *  (ob is not in editmode)
 */
static void separate_armature_bones(Object *ob, short sel) 
{
	bArmature *arm = (bArmature *)ob->data;
	bPoseChannel *pchan, *pchann;
	EditBone *curbone;
	
	/* make local set of editbones to manipulate here */
	ED_armature_to_edit(ob);
	
	/* 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(arm->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 = arm->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 ED_armature_from_edit */
					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 */
			BKE_pose_channel_free(pchan);
			BKE_pose_channels_hash_free(ob->pose);
			
			/* get rid of unneeded bone */
			bone_free(arm, curbone);
			BLI_freelinkN(&ob->pose->chanbase, pchan);
		}
	}
	
	/* exit editmode (recalculates pchans too) */
	ED_armature_from_edit(ob);
	ED_armature_edit_free(ob);
}
示例#2
0
void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone)
{
	EditBone *curBone;

	/* Find any bones that refer to this bone */
	for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
		if (curBone->parent == exBone) {
			curBone->parent = exBone->parent;
			curBone->flag &= ~BONE_CONNECTED;
		}
	}

	bone_free(arm, exBone);
}
示例#3
0
/* this function merges between two bones, removes them and those in-between, 
 * and adjusts the parent relationships for those in-between
 */
static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone *endchild, ListBase *chains)
{
	bArmature *arm = obedit->data;
	EditBone *ebo, *ebone, *newbone;
	LinkData *chain;
	float head[3], tail[3];
	
	/* check if same bone */
	if (start == end) {
		if (G.debug & G_DEBUG) {
			printf("Error: same bone!\n");
			printf("\tstart = %s, end = %s\n", start->name, end->name);
		}
	}
	
	/* step 1: add a new bone
	 *	- head = head/tail of start (default head)
	 *	- tail = head/tail of end (default tail)
	 *	- parent = parent of start
	 */
	if ((start->flag & BONE_TIPSEL) && (start->flag & BONE_SELECTED) == 0) {
		copy_v3_v3(head, start->tail);
	}
	else {
		copy_v3_v3(head, start->head);
	}
	if ((end->flag & BONE_ROOTSEL) && (end->flag & BONE_SELECTED) == 0) {
		copy_v3_v3(tail, end->head);
	}
	else {
		copy_v3_v3(tail, end->tail);
	}
	newbone = add_points_bone(obedit, head, tail);
	newbone->parent = start->parent;

	/* TODO, copy more things to the new bone */
	newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_SCALE |
	                               BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE);
	
	/* step 2a: reparent any side chains which may be parented to any bone in the chain of bones to merge 
	 *	- potentially several tips for side chains leading to some tree exist...
	 */
	for (chain = chains->first; chain; chain = chain->next) {
		/* traverse down chain until we hit the bottom or if we run into the tip of the chain of bones we're 
		 * merging (need to stop in this case to avoid corrupting this chain too!) 
		 */
		for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) {
			short found = 0;
			
			/* check if this bone is parented to one in the merging chain
			 * ! WATCHIT: must only go check until end of checking chain
			 */
			for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) {
				/* side-chain found? --> remap parent to new bone, then we're done with this chain :) */
				if (ebone->parent == ebo) {
					ebone->parent = newbone;
					found = 1;
					break;
				}
			}
			
			/* carry on to the next tip now  */
			if (found) 
				break;
		}
	}
	
	/* step 2b: parent child of end to newbone (child from this chain) */
	if (endchild)
		endchild->parent = newbone;
	
	/* step 3: delete all bones between and including start and end */
	for (ebo = end; ebo; ebo = ebone) {
		ebone = (ebo == start) ? (NULL) : (ebo->parent);
		bone_free(arm, ebo);
	}
	
	newbone->flag |= (BONE_ROOTSEL | BONE_TIPSEL | BONE_SELECTED);
	ED_armature_sync_selection(arm->edbo);
}
示例#4
0
/* put EditMode back in Object */
void ED_armature_from_edit(bArmature *arm)
{
	EditBone *eBone, *neBone;
	Bone *newBone;
	Object *obt;
	
	/* armature bones */
	BKE_armature_bonelist_free(&arm->bonebase);
	arm->act_bone = NULL;
	
	/* remove zero sized bones, this gives unstable restposes */
	for (eBone = arm->edbo->first; eBone; eBone = neBone) {
		float len_sq = len_squared_v3v3(eBone->head, eBone->tail);
		neBone = eBone->next;
		if (len_sq <= SQUARE(0.000001f)) {  /* FLT_EPSILON is too large? */
			EditBone *fBone;
			
			/* Find any bones that refer to this bone */
			for (fBone = arm->edbo->first; fBone; fBone = fBone->next) {
				if (fBone->parent == eBone)
					fBone->parent = eBone->parent;
			}
			if (G.debug & G_DEBUG)
				printf("Warning: removed zero sized bone: %s\n", eBone->name);
			bone_free(arm, eBone);
		}
	}
	
	/*	Copy the bones from the editData into the armature */
	for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
		newBone = MEM_callocN(sizeof(Bone), "bone");
		eBone->temp.bone = newBone;   /* Associate the real Bones with the EditBones */
		
		BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
		copy_v3_v3(newBone->arm_head, eBone->head);
		copy_v3_v3(newBone->arm_tail, eBone->tail);
		newBone->arm_roll = eBone->roll;
		
		newBone->flag = eBone->flag;
		
		if (eBone == arm->act_edbone) {
			/* don't change active selection, this messes up separate which uses
			 * editmode toggle and can separate active bone which is de-selected originally */
			/* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */
			arm->act_bone = newBone;
		}
		newBone->roll = 0.0f;
		
		newBone->weight = eBone->weight;
		newBone->dist = eBone->dist;
		
		newBone->xwidth = eBone->xwidth;
		newBone->zwidth = eBone->zwidth;
		newBone->rad_head = eBone->rad_head;
		newBone->rad_tail = eBone->rad_tail;
		newBone->segments = eBone->segments;
		newBone->layer = eBone->layer;

		/* Bendy-Bone parameters */
		newBone->roll1 = eBone->roll1;
		newBone->roll2 = eBone->roll2;
		newBone->curveInX = eBone->curveInX;
		newBone->curveInY = eBone->curveInY;
		newBone->curveOutX = eBone->curveOutX;
		newBone->curveOutY = eBone->curveOutY;
		newBone->ease1 = eBone->ease1;
		newBone->ease2 = eBone->ease2;
		newBone->scaleIn = eBone->scaleIn;
		newBone->scaleOut = eBone->scaleOut;


		if (eBone->prop)
			newBone->prop = IDP_CopyProperty(eBone->prop);
	}
	
	/* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point.
	 * Do not set bone->head/tail here anymore, using EditBone data for that is not OK since our later fiddling
	 * with parent's arm_mat (for roll conversion) may have some small but visible impact on locations (T46010). */
	for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
		newBone = eBone->temp.bone;
		if (eBone->parent) {
			newBone->parent = eBone->parent->temp.bone;
			BLI_addtail(&newBone->parent->childbase, newBone);
		}
		/*	...otherwise add this bone to the armature's bonebase */
		else {
			BLI_addtail(&arm->bonebase, newBone);
		}
	}
	
	/* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */
	armature_finalize_restpose(&arm->bonebase, arm->edbo);
	
	/* so all users of this armature should get rebuilt */
	for (obt = G.main->object.first; obt; obt = obt->id.next) {
		if (obt->data == arm) {
			BKE_pose_rebuild(obt, arm);
		}
	}
	
	DAG_id_tag_update(&arm->id, 0);
}
示例#5
0
/* put EditMode back in Object */
void ED_armature_from_edit(bArmature *arm)
{
	EditBone *eBone, *neBone;
	Bone *newBone;
	Object *obt;
	
	/* armature bones */
	BKE_armature_bonelist_free(&arm->bonebase);
	arm->act_bone = NULL;
	
	/* remove zero sized bones, this gives unstable restposes */
	for (eBone = arm->edbo->first; eBone; eBone = neBone) {
		float len = len_v3v3(eBone->head, eBone->tail);
		neBone = eBone->next;
		if (len <= 0.000001f) {  /* FLT_EPSILON is too large? */
			EditBone *fBone;
			
			/*	Find any bones that refer to this bone	*/
			for (fBone = arm->edbo->first; fBone; fBone = fBone->next) {
				if (fBone->parent == eBone)
					fBone->parent = eBone->parent;
			}
			if (G.debug & G_DEBUG)
				printf("Warning: removed zero sized bone: %s\n", eBone->name);
			bone_free(arm, eBone);
		}
	}
	
	/*	Copy the bones from the editData into the armature */
	for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
		newBone = MEM_callocN(sizeof(Bone), "bone");
		eBone->temp.bone = newBone;   /* Associate the real Bones with the EditBones */
		
		BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
		copy_v3_v3(newBone->arm_head, eBone->head);
		copy_v3_v3(newBone->arm_tail, eBone->tail);
		newBone->arm_roll = eBone->roll;
		
		newBone->flag = eBone->flag;
		
		if (eBone == arm->act_edbone) {
			/* don't change active selection, this messes up separate which uses
			 * editmode toggle and can separate active bone which is de-selected originally */
			/* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */
			arm->act_bone = newBone;
		}
		newBone->roll = 0.0f;
		
		newBone->weight = eBone->weight;
		newBone->dist = eBone->dist;
		
		newBone->xwidth = eBone->xwidth;
		newBone->zwidth = eBone->zwidth;
		newBone->ease1 = eBone->ease1;
		newBone->ease2 = eBone->ease2;
		newBone->rad_head = eBone->rad_head;
		newBone->rad_tail = eBone->rad_tail;
		newBone->segments = eBone->segments;
		newBone->layer = eBone->layer;
		
		if (eBone->prop)
			newBone->prop = IDP_CopyProperty(eBone->prop);
	}
	
	/* Fix parenting in a separate pass to ensure ebone->bone connections
	 * are valid at this point */
	for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
		newBone = eBone->temp.bone;
		if (eBone->parent) {
			newBone->parent = eBone->parent->temp.bone;
			BLI_addtail(&newBone->parent->childbase, newBone);
			
			{
				float M_parentRest[3][3];
				float iM_parentRest[3][3];
				
				/* Get the parent's  matrix (rotation only) */
				ED_armature_ebone_to_mat3(eBone->parent, M_parentRest);
				
				/* Invert the parent matrix */
				invert_m3_m3(iM_parentRest, M_parentRest);
				
				/* Get the new head and tail */
				sub_v3_v3v3(newBone->head, eBone->head, eBone->parent->tail);
				sub_v3_v3v3(newBone->tail, eBone->tail, eBone->parent->tail);
				
				mul_m3_v3(iM_parentRest, newBone->head);
				mul_m3_v3(iM_parentRest, newBone->tail);
			}
		}
		/*	...otherwise add this bone to the armature's bonebase */
		else {
			copy_v3_v3(newBone->head, eBone->head);
			copy_v3_v3(newBone->tail, eBone->tail);
			BLI_addtail(&arm->bonebase, newBone);
		}
	}
	
	/* Make a pass through the new armature to fix rolling */
	/* also builds restposition again (like BKE_armature_where_is) */
	fix_bonelist_roll(&arm->bonebase, arm->edbo);
	
	/* so all users of this armature should get rebuilt */
	for (obt = G.main->object.first; obt; obt = obt->id.next) {
		if (obt->data == arm)
			BKE_pose_rebuild(obt, arm);
	}
	
	DAG_id_tag_update(&arm->id, 0);
}