예제 #1
0
/* XXX should be used everywhere, now it mallocs bones still locally in functions */
EditBone *ED_armature_edit_bone_add(bArmature *arm, const char *name)
{
	EditBone *bone = MEM_callocN(sizeof(EditBone), "eBone");
	
	BLI_strncpy(bone->name, name, sizeof(bone->name));
	unique_editbone_name(arm->edbo, bone->name, NULL);
	
	BLI_addtail(arm->edbo, bone);
	
	bone->flag |= BONE_TIPSEL;
	bone->weight = 1.0f;
	bone->dist = 0.25f;
	bone->xwidth = 0.1f;
	bone->zwidth = 0.1f;
	bone->ease1 = 1.0f;
	bone->ease2 = 1.0f;
	bone->rad_head = 0.10f;
	bone->rad_tail = 0.05f;
	bone->segments = 1;
	bone->layer = arm->layer;
	
	bone->roll1 = 0.0f;
	bone->roll2 = 0.0f;
	bone->curveInX = 0.0f;
	bone->curveInY = 0.0f;
	bone->curveOutX = 0.0f;
	bone->curveOutY = 0.0f;
	bone->scaleIn = 1.0f;
	bone->scaleOut = 1.0f;

	return bone;
}
예제 #2
0
EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase *editbones,
                                   Object *src_ob, Object *dst_ob)
{
	EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
	
	/*	Copy data from old bone to new bone */
	memcpy(eBone, curBone, sizeof(EditBone));
	
	curBone->temp.ebone = eBone;
	eBone->temp.ebone = curBone;
	
	if (name != NULL) {
		BLI_strncpy(eBone->name, name, sizeof(eBone->name));
	}

	unique_editbone_name(editbones, eBone->name, NULL);
	BLI_addtail(editbones, eBone);
	
	/* copy the ID property */
	if (curBone->prop)
		eBone->prop = IDP_CopyProperty(curBone->prop);

	/* Lets duplicate the list of constraints that the
	 * current bone has.
	 */
	if (src_ob->pose) {
		bPoseChannel *chanold, *channew;
		
		chanold = BKE_pose_channel_verify(src_ob->pose, curBone->name);
		if (chanold) {
			/* WARNING: this creates a new posechannel, but there will not be an attached bone
			 *		yet as the new bones created here are still 'EditBones' not 'Bones'.
			 */
			channew = BKE_pose_channel_verify(dst_ob->pose, eBone->name);

			if (channew) {
				BKE_pose_channel_copy_data(channew, chanold);
			}
		}
	}
	
	return eBone;
}
예제 #3
0
/* seems messy, but thats what you get with not using pointers but channel names :) */
void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *newnamep)
{
	Object *ob;
	char newname[MAXBONENAME];
	char oldname[MAXBONENAME];
	
	/* names better differ! */
	if (strncmp(oldnamep, newnamep, MAXBONENAME)) {
		
		/* we alter newname string... so make copy */
		BLI_strncpy(newname, newnamep, MAXBONENAME);
		/* we use oldname for search... so make copy */
		BLI_strncpy(oldname, oldnamep, MAXBONENAME);
		
		/* now check if we're in editmode, we need to find the unique name */
		if (arm->edbo) {
			EditBone *eBone = ED_armature_bone_find_name(arm->edbo, oldname);
			
			if (eBone) {
				unique_editbone_name(arm->edbo, newname, NULL);
				BLI_strncpy(eBone->name, newname, MAXBONENAME);
			}
			else {
				return;
			}
		}
		else {
			Bone *bone = BKE_armature_find_bone_name(arm, oldname);
			
			if (bone) {
				unique_bone_name(arm, newname);
				BLI_strncpy(bone->name, newname, MAXBONENAME);
			}
			else {
				return;
			}
		}
		
		/* do entire dbase - objects */
		for (ob = G.main->object.first; ob; ob = ob->id.next) {
			ModifierData *md;
			
			/* we have the object using the armature */
			if (arm == ob->data) {
				Object *cob;
				
				/* Rename the pose channel, if it exists */
				if (ob->pose) {
					bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname);
					if (pchan) {
						GHash *gh = ob->pose->chanhash;

						/* remove the old hash entry, and replace with the new name */
						if (gh) {
							BLI_assert(BLI_ghash_haskey(gh, pchan->name));
							BLI_ghash_remove(gh, pchan->name, NULL, NULL);
						}

						BLI_strncpy(pchan->name, newname, MAXBONENAME);

						if (gh) {
							BLI_ghash_insert(gh, pchan->name, pchan);
						}
					}

					BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true);
				}
				
				/* Update any object constraints to use the new bone name */
				for (cob = G.main->object.first; cob; cob = cob->id.next) {
					if (cob->constraints.first)
						constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
					if (cob->pose) {
						bPoseChannel *pchan;
						for (pchan = cob->pose->chanbase.first; pchan; pchan = pchan->next) {
							constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
						}
					}
				}
			}
			
			/* See if an object is parented to this armature */
			if (ob->parent && (ob->parent->data == arm)) {
				if (ob->partype == PARBONE) {
					/* bone name in object */
					if (!strcmp(ob->parsubstr, oldname))
						BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
				}
			}
			
			if (modifiers_usesArmature(ob, arm)) {
				bDeformGroup *dg = defgroup_find_name(ob, oldname);
				if (dg) {
					BLI_strncpy(dg->name, newname, MAXBONENAME);
				}
			}
			
			/* fix modifiers that might be using this name */
			for (md = ob->modifiers.first; md; md = md->next) {
				switch (md->type) {
					case eModifierType_Hook:
					{
						HookModifierData *hmd = (HookModifierData *)md;

						if (hmd->object && (hmd->object->data == arm)) {
							if (STREQ(hmd->subtarget, oldname))
								BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
						}
						break;
					}
					case eModifierType_UVWarp:
					{
						UVWarpModifierData *umd = (UVWarpModifierData *)md;

						if (umd->object_src && (umd->object_src->data == arm)) {
							if (STREQ(umd->bone_src, oldname))
								BLI_strncpy(umd->bone_src, newname, MAXBONENAME);
						}
						if (umd->object_dst && (umd->object_dst->data == arm)) {
							if (STREQ(umd->bone_dst, oldname))
								BLI_strncpy(umd->bone_dst, newname, MAXBONENAME);
						}
						break;
					}
					default:
						break;
				}
			}
		}
		
		/* Fix all animdata that may refer to this bone - we can't just do the ones attached to objects, since
		 * other ID-blocks may have drivers referring to this bone [#29822]
		 */
		{
			
			BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname);
		}
		
		/* correct view locking */
		{
			bScreen *screen;
			for (screen = G.main->screen.first; screen; screen = screen->id.next) {
				ScrArea *sa;
				/* add regions */
				for (sa = screen->areabase.first; sa; sa = sa->next) {
					SpaceLink *sl;
					for (sl = sa->spacedata.first; sl; sl = sl->next) {
						if (sl->spacetype == SPACE_VIEW3D) {
							View3D *v3d = (View3D *)sl;
							if (v3d->ob_centre && v3d->ob_centre->data == arm) {
								if (!strcmp(v3d->ob_centre_bone, oldname)) {
									BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
								}
							}
						}
					}
				}
			}
		}
	}
}
예제 #4
0
/* if forked && mirror-edit: makes two bones with flipped names */
static int armature_extrude_exec(bContext *C, wmOperator *op)
{
	Object *obedit;
	bArmature *arm;
	EditBone *newbone, *ebone, *flipbone, *first = NULL;
	int a, totbone = 0, do_extrude;
	bool forked = RNA_boolean_get(op->ptr, "forked");

	obedit = CTX_data_edit_object(C);
	arm = obedit->data;

	/* since we allow root extrude too, we have to make sure selection is OK */
	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
		if (EBONE_VISIBLE(arm, ebone)) {
			if (ebone->flag & BONE_ROOTSEL) {
				if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
					if (ebone->parent->flag & BONE_TIPSEL)
						ebone->flag &= ~BONE_ROOTSEL;
				}
			}
		}
	}
	
	/* Duplicate the necessary bones */
	for (ebone = arm->edbo->first; ((ebone) && (ebone != first)); ebone = ebone->next) {
		if (EBONE_VISIBLE(arm, ebone)) {
			/* we extrude per definition the tip */
			do_extrude = false;
			if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED)) {
				do_extrude = true;
			}
			else if (ebone->flag & BONE_ROOTSEL) {
				/* but, a bone with parent deselected we do the root... */
				if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL)) {
					/* pass */
				}
				else {
					do_extrude = 2;
				}
			}
			
			if (do_extrude) {
				/* we re-use code for mirror editing... */
				flipbone = NULL;
				if (arm->flag & ARM_MIRROR_EDIT) {
					flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
					if (flipbone) {
						forked = 0;  // we extrude 2 different bones
						if (flipbone->flag & (BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED))
							/* don't want this bone to be selected... */
							flipbone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
					}
					if ((flipbone == NULL) && (forked))
						flipbone = ebone;
				}
				
				for (a = 0; a < 2; a++) {
					if (a == 1) {
						if (flipbone == NULL)
							break;
						else {
							SWAP(EditBone *, flipbone, ebone);
						}
					}
					
					totbone++;
					newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
					
					if (do_extrude == true) {
						copy_v3_v3(newbone->head, ebone->tail);
						copy_v3_v3(newbone->tail, newbone->head);
						newbone->parent = ebone;
						
						newbone->flag = ebone->flag & (BONE_TIPSEL | BONE_RELATIVE_PARENTING);  // copies it, in case mirrored bone
						
						if (newbone->parent) newbone->flag |= BONE_CONNECTED;
					}
					else {
						copy_v3_v3(newbone->head, ebone->head);
						copy_v3_v3(newbone->tail, ebone->head);
						newbone->parent = ebone->parent;
						
						newbone->flag = BONE_TIPSEL;
						
						if (newbone->parent && (ebone->flag & BONE_CONNECTED)) {
							newbone->flag |= BONE_CONNECTED;
						}
					}
					
					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_tail; // don't copy entire bone...
					newbone->rad_tail = ebone->rad_tail;
					newbone->segments = 1;
					newbone->layer = ebone->layer;
					
					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->scaleIn = ebone->scaleIn;
					newbone->scaleOut = ebone->scaleOut;


					BLI_strncpy(newbone->name, ebone->name, sizeof(newbone->name));
					
					if (flipbone && forked) {   // only set if mirror edit
						if (strlen(newbone->name) < (MAXBONENAME - 2)) {
							if (a == 0) strcat(newbone->name, "_L");
							else strcat(newbone->name, "_R");
						}
					}
					unique_editbone_name(arm->edbo, newbone->name, NULL);
					
					/* Add the new bone to the list */
					BLI_addtail(arm->edbo, newbone);
					if (!first)
						first = newbone;
					
					/* restore ebone if we were flipping */
					if (a == 1 && flipbone)
						SWAP(EditBone *, flipbone, ebone);
				}
			}
			
			/* Deselect the old bone */
			ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
		}
	}
	/* if only one bone, make this one active */
	if (totbone == 1 && first) arm->act_edbone = first;

	if (totbone == 0) return OPERATOR_CANCELLED;

	/* Transform the endpoints */
	ED_armature_sync_selection(arm->edbo);

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);

	return OPERATOR_FINISHED;
}
예제 #5
0
static int armature_subdivide_exec(bContext *C, wmOperator *op)
{
	Object *obedit = CTX_data_edit_object(C);
	bArmature *arm = obedit->data;
	EditBone *newbone, *tbone;
	int cuts, i;
	
	/* there may not be a number_cuts property defined (for 'simple' subdivide) */
	cuts = RNA_int_get(op->ptr, "number_cuts");
	
	/* loop over all editable bones */
	// XXX the old code did this in reverse order though!
	CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
	{
		for (i = cuts + 1; i > 1; i--) {
			/* compute cut ratio first */
			float cutratio = 1.0f / (float)i;
			float cutratioI = 1.0f - cutratio;
			
			float val1[3];
			float val2[3];
			float val3[3];
			
			newbone = MEM_mallocN(sizeof(EditBone), "ebone subdiv");
			*newbone = *ebone;
			BLI_addtail(arm->edbo, newbone);
			
			/* calculate location of newbone->head */
			copy_v3_v3(val1, ebone->head);
			copy_v3_v3(val2, ebone->tail);
			copy_v3_v3(val3, newbone->head);
			
			val3[0] = val1[0] * cutratio + val2[0] * cutratioI;
			val3[1] = val1[1] * cutratio + val2[1] * cutratioI;
			val3[2] = val1[2] * cutratio + val2[2] * cutratioI;
			
			copy_v3_v3(newbone->head, val3);
			copy_v3_v3(newbone->tail, ebone->tail);
			copy_v3_v3(ebone->tail, newbone->head);
			
			newbone->rad_head = ((ebone->rad_head * cutratio) + (ebone->rad_tail * cutratioI));
			ebone->rad_tail = newbone->rad_head;
			
			newbone->flag |= BONE_CONNECTED;

			newbone->prop = NULL;

			unique_editbone_name(arm->edbo, newbone->name, NULL);
			
			/* correct parent bones */
			for (tbone = arm->edbo->first; tbone; tbone = tbone->next) {
				if (tbone->parent == ebone)
					tbone->parent = newbone;
			}
			newbone->parent = ebone;
		}
	}
	CTX_DATA_END;
	
	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
	
	return OPERATOR_FINISHED;
}
예제 #6
0
/* join armature exec is exported for use in object->join objects operator... */
int join_armature_exec(bContext *C, wmOperator *UNUSED(op))
{
	Main *bmain = CTX_data_main(C);
	Scene *scene = CTX_data_scene(C);
	Object  *ob = CTX_data_active_object(C);
	bArmature *arm = (ob) ? ob->data : NULL;
	bPose *pose, *opose;
	bPoseChannel *pchan, *pchann;
	EditBone *curbone;
	float mat[4][4], oimat[4][4];
	
	/*	Ensure we're not in editmode and that the active object is an armature*/
	if (!ob || ob->type != OB_ARMATURE)
		return OPERATOR_CANCELLED;
	if (!arm || arm->edbo)
		return OPERATOR_CANCELLED;
	
	/* Get editbones of active armature to add editbones to */
	ED_armature_to_edit(ob);
	
	/* get pose of active object and move it out of posemode */
	pose = ob->pose;
	ob->mode &= ~OB_MODE_POSE;

	CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
	{
		if ((base->object->type == OB_ARMATURE) && (base->object != ob)) {
			bArmature *curarm = base->object->data;
			
			/* Make a list of editbones in current armature */
			ED_armature_to_edit(base->object);
			
			/* Get Pose of current armature */
			opose = base->object->pose;
			base->object->mode &= ~OB_MODE_POSE;
			//BASACT->flag &= ~OB_MODE_POSE;
			
			/* Find the difference matrix */
			invert_m4_m4(oimat, ob->obmat);
			mult_m4_m4m4(mat, oimat, base->object->obmat);
			
			/* Copy bones and posechannels from the object to the edit armature */
			for (pchan = opose->chanbase.first; pchan; pchan = pchann) {
				pchann = pchan->next;
				curbone = editbone_name_exists(curarm->edbo, pchan->name);
				
				/* Get new name */
				unique_editbone_name(arm->edbo, curbone->name, NULL);
				
				/* Transform the bone */
				{
					float premat[4][4];
					float postmat[4][4];
					float difmat[4][4];
					float imat[4][4];
					float temp[3][3];
					float delta[3];
					
					/* Get the premat */
					sub_v3_v3v3(delta, curbone->tail, curbone->head);
					vec_roll_to_mat3(delta, curbone->roll, temp);
					
					unit_m4(premat); /* Mat4MulMat34 only sets 3x3 part */
					mul_m4_m3m4(premat, temp, mat);
					
					mul_m4_v3(mat, curbone->head);
					mul_m4_v3(mat, curbone->tail);
					
					/* Get the postmat */
					sub_v3_v3v3(delta, curbone->tail, curbone->head);
					vec_roll_to_mat3(delta, curbone->roll, temp);
					copy_m4_m3(postmat, temp);
					
					/* Find the roll */
					invert_m4_m4(imat, premat);
					mult_m4_m4m4(difmat, imat, postmat);
					
					curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
				}
				
				/* Fix Constraints and Other Links to this Bone and Armature */
				joined_armature_fix_links(ob, base->object, pchan, curbone);
				
				/* Rename pchan */
				BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
				
				/* Jump Ship! */
				BLI_remlink(curarm->edbo, curbone);
				BLI_addtail(arm->edbo, curbone);
				
				BLI_remlink(&opose->chanbase, pchan);
				BLI_addtail(&pose->chanbase, pchan);
				BKE_pose_channels_hash_free(opose);
				BKE_pose_channels_hash_free(pose);
			}
			
			ED_base_object_free_and_unlink(bmain, scene, base);
		}
	}
	CTX_DATA_END;
	
	DAG_relations_tag_update(bmain);  /* because we removed object(s) */

	ED_armature_from_edit(ob);
	ED_armature_edit_free(ob);

	WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
	
	return OPERATOR_FINISHED;
}