/* v3d and rv3d are allowed to be NULL */
void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
{
	Object *obedit = scene->obedit; // XXX get from context
	bArmature *arm = obedit->data;
	float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
	EditBone    *bone;

	/* Get inverse point for head and orientation for tail */
	invert_m4_m4(obedit->imat, obedit->obmat);
	mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));

	if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
		copy_m3_m4(obmat, rv3d->viewmat);
	else unit_m3(obmat);
	
	copy_m3_m4(viewmat, obedit->obmat);
	mul_m3_m3m3(totmat, obmat, viewmat);
	invert_m3_m3(imat, totmat);
	
	ED_armature_deselect_all(obedit, 0);
	
	/* Create a bone */
	bone = ED_armature_edit_bone_add(arm, "Bone");

	arm->act_edbone = bone;

	copy_v3_v3(bone->head, curs);
	
	if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
		add_v3_v3v3(bone->tail, bone->head, imat[1]);   // bone with unit length 1
	else
		add_v3_v3v3(bone->tail, bone->head, imat[2]);   // bone with unit length 1, pointing up Z
}
示例#2
0
static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set)
{
	bArmature *arm= scene->obedit->data;
	EditBone *ebone= te->directdata;

	if(set==1) {
		if(!(ebone->flag & BONE_HIDDEN_A)) {
			ED_armature_deselect_all(scene->obedit, 0);	// deselect
			tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE);
			return 1;
		}
	}
	else if (set==2) {
		if(!(ebone->flag & BONE_HIDDEN_A)) {
			if(!(ebone->flag & BONE_SELECTED)) {
				tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE);
				return 1;
			}
			else {
				/* entirely selected, so de-select */
				tree_element_active_ebone__sel(C, scene, arm, ebone, FALSE);
				return 0;
			}
		}
	}
	else if (ebone->flag & BONE_SELECTED) {
		return 1;
	}
	return 0;
}
EditBone *ED_armature_edit_bone_add_primitive(Object *obedit_arm, float length, bool view_aligned)
{
	bArmature *arm = obedit_arm->data;
	EditBone *bone;

	ED_armature_deselect_all(obedit_arm);
	
	/* Create a bone */
	bone = ED_armature_edit_bone_add(arm, "Bone");

	arm->act_edbone = bone;

	zero_v3(bone->head);
	zero_v3(bone->tail);

	bone->tail[view_aligned ? 1 : 2] = length;

	return bone;
}
示例#4
0
void add_primitive_bone(Object *obedit_arm, bool view_aligned)
{
	bArmature *arm = obedit_arm->data;
	EditBone *bone;

	ED_armature_deselect_all(obedit_arm, 0);
	
	/* Create a bone */
	bone = ED_armature_edit_bone_add(arm, "Bone");

	arm->act_edbone = bone;

	zero_v3(bone->head);
	zero_v3(bone->tail);

	if (view_aligned)
		bone->tail[1] = 1.0f;
	else
		bone->tail[2] = 1.0f;
}
static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) 
{
	RegionView3D *rv3d = CTX_wm_region_view3d(C);
	Object *obedit = CTX_data_edit_object(C);
	EditBone *bone;
	float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
	char name[MAXBONENAME];
	
	RNA_string_get(op->ptr, "name", name);
	
	copy_v3_v3(curs, ED_view3d_cursor3d_get(CTX_data_scene(C), CTX_wm_view3d(C)));

	/* Get inverse point for head and orientation for tail */
	invert_m4_m4(obedit->imat, obedit->obmat);
	mul_m4_v3(obedit->imat, curs);

	if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
		copy_m3_m4(obmat, rv3d->viewmat);
	else unit_m3(obmat);
	
	copy_m3_m4(viewmat, obedit->obmat);
	mul_m3_m3m3(totmat, obmat, viewmat);
	invert_m3_m3(imat, totmat);
	
	ED_armature_deselect_all(obedit);
	
	/*	Create a bone	*/
	bone = ED_armature_edit_bone_add(obedit->data, name);

	copy_v3_v3(bone->head, curs);
	
	if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
		add_v3_v3v3(bone->tail, bone->head, imat[1]);   // bone with unit length 1
	else
		add_v3_v3v3(bone->tail, bone->head, imat[2]);   // bone with unit length 1, pointing up Z

	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);

	return OPERATOR_FINISHED;
}
示例#6
0
static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set, bool recursive)
{
	bArmature *arm = scene->obedit->data;
	EditBone *ebone = te->directdata;
	int status = 0;
	if (set) {
		if (set == 1) {
			if (!(ebone->flag & BONE_HIDDEN_A)) {
				ED_armature_deselect_all(scene->obedit, 0); // deselect
				tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE);
				status = 1;
			}
		}
		else if (set == 2) {
			if (!(ebone->flag & BONE_HIDDEN_A)) {
				if (!(ebone->flag & BONE_SELECTED)) {
					tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE);
					status = 1;
				}
				else {
					/* entirely selected, so de-select */
					tree_element_active_ebone__sel(C, scene, arm, ebone, FALSE);
					status = 0;
				}
			}
		}

		if (recursive) {
			/* Recursive select/deselect */
			do_outliner_ebone_select_recursive(arm, ebone, (ebone->flag & BONE_SELECTED) != 0);
		}
	}
	else if (ebone->flag & BONE_SELECTED) {
		status = 1;
	}
	return status;
}
/* the ctrl-click method */
static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
	View3D *v3d;
	bArmature *arm;
	EditBone *ebone, *newbone, *flipbone;
	float mat[3][3], imat[3][3];
	const float *curs;
	int a, to_root = 0;
	Object *obedit;
	Scene *scene;

	scene = CTX_data_scene(C);
	v3d = CTX_wm_view3d(C);
	obedit = CTX_data_edit_object(C);
	arm = obedit->data;
	
	/* find the active or selected bone */
	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
		if (EBONE_VISIBLE(arm, ebone)) {
			if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
				break;
		}
	}
	
	if (ebone == NULL) {
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone)) {
				if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
					break;
			}
		}
		if (ebone == NULL) 
			return OPERATOR_CANCELLED;
		
		to_root = 1;
	}
	
	ED_armature_deselect_all(obedit);
	
	/* we re-use code for mirror editing... */
	flipbone = NULL;
	if (arm->flag & ARM_MIRROR_EDIT)
		flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);

	for (a = 0; a < 2; a++) {
		if (a == 1) {
			if (flipbone == NULL)
				break;
			else {
				SWAP(EditBone *, flipbone, ebone);
			}
		}
		
		newbone = ED_armature_edit_bone_add(arm, ebone->name);
		arm->act_edbone = newbone;
		
		if (to_root) {
			copy_v3_v3(newbone->head, ebone->head);
			newbone->rad_head = ebone->rad_tail;
			newbone->parent = ebone->parent;
		}
		else {
			copy_v3_v3(newbone->head, ebone->tail);
			newbone->rad_head = ebone->rad_tail;
			newbone->parent = ebone;
			newbone->flag |= BONE_CONNECTED;
		}
		
		curs = ED_view3d_cursor3d_get(scene, v3d);
		copy_v3_v3(newbone->tail, curs);
		sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
		
		if (a == 1)
			newbone->tail[0] = -newbone->tail[0];
		
		copy_m3_m4(mat, obedit->obmat);
		invert_m3_m3(imat, mat);
		mul_m3_v3(imat, newbone->tail);
		
		newbone->length = len_v3v3(newbone->head, newbone->tail);
		newbone->rad_tail = newbone->length * 0.05f;
		newbone->dist = newbone->length * 0.25f;
		
	}
	
	ED_armature_sync_selection(arm->edbo);

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
	
	return OPERATOR_FINISHED;
}
示例#8
0
/* context: editmode armature in view3d */
bool mouse_armature(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
	Object *obedit = CTX_data_edit_object(C);
	bArmature *arm = obedit->data;
	ViewContext vc;
	EditBone *nearBone = NULL;
	int selmask;

	view3d_set_viewcontext(C, &vc);
	
	BIF_sk_selectStroke(C, mval, extend);
	
	nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
	if (nearBone) {

		if (!extend && !deselect && !toggle)
			ED_armature_deselect_all(obedit, 0);
		
		/* by definition the non-root connected bones have no root point drawn,
		 * so a root selection needs to be delivered to the parent tip */
		
		if (selmask & BONE_SELECTED) {
			if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
				/* click in a chain */
				if (extend) {
					/* select this bone */
					nearBone->flag |= BONE_TIPSEL;
					nearBone->parent->flag |= BONE_TIPSEL;
				}
				else if (deselect) {
					/* deselect this bone */
					nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
					/* only deselect parent tip if it is not selected */
					if (!(nearBone->parent->flag & BONE_SELECTED))
						nearBone->parent->flag &= ~BONE_TIPSEL;
				}
				else if (toggle) {
					/* hold shift inverts this bone's selection */
					if (nearBone->flag & BONE_SELECTED) {
						/* deselect this bone */
						nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
						/* only deselect parent tip if it is not selected */
						if (!(nearBone->parent->flag & BONE_SELECTED))
							nearBone->parent->flag &= ~BONE_TIPSEL;
					}
					else {
						/* select this bone */
						nearBone->flag |= BONE_TIPSEL;
						nearBone->parent->flag |= BONE_TIPSEL;
					}
				}
				else {
					/* select this bone */
					nearBone->flag |= BONE_TIPSEL;
					nearBone->parent->flag |= BONE_TIPSEL;
				}
			}
			else {
				if (extend) {
					nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
				}
				else if (deselect) {
					nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
				}
				else if (toggle) {
					/* hold shift inverts this bone's selection */
					if (nearBone->flag & BONE_SELECTED)
						nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
					else
						nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
				}
				else
					nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
			}
		}
		else {
			if (extend)
				nearBone->flag |= selmask;
			else if (deselect)
				nearBone->flag &= ~selmask;
			else if (toggle && (nearBone->flag & selmask))
				nearBone->flag &= ~selmask;
			else
				nearBone->flag |= selmask;
		}
		
		ED_armature_sync_selection(arm->edbo);
		
		if (nearBone) {
			/* then now check for active status */
			if (ebone_select_flag(nearBone)) {
				arm->act_edbone = nearBone;
			}
		}
		
		WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
		return true;
	}

	return false;
}
示例#9
0
/* bone adding between selected joints */
static int armature_fill_bones_exec(bContext *C, wmOperator *op)
{
	Object *obedit = CTX_data_edit_object(C);
	bArmature *arm = (obedit) ? obedit->data : NULL;
	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);
	ListBase points = {NULL, NULL};
	EditBone *newbone = NULL;
	int count;

	/* sanity checks */
	if (ELEM(NULL, obedit, arm))
		return OPERATOR_CANCELLED;

	/* loop over all bones, and only consider if visible */
	CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
	{
		if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
			fill_add_joint(ebone, 0, &points);
		if (ebone->flag & BONE_TIPSEL) 
			fill_add_joint(ebone, 1, &points);
	}
	CTX_DATA_END;
	
	/* the number of joints determines how we fill:
	 *  1) between joint and cursor (joint=head, cursor=tail)
	 *  2) between the two joints (order is dependent on active-bone/hierarchy)
	 *  3+) error (a smarter method involving finding chains needs to be worked out
	 */
	count = BLI_listbase_count(&points);
	
	if (count == 0) {
		BKE_report(op->reports, RPT_ERROR, "No joints selected");
		return OPERATOR_CANCELLED;
	}
	else if (count == 1) {
		EditBonePoint *ebp;
		float curs[3];
		
		/* Get Points - selected joint */
		ebp = points.first;
		
		/* Get points - cursor (tail) */
		invert_m4_m4(obedit->imat, obedit->obmat);
		mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
		
		/* Create a bone */
		newbone = add_points_bone(obedit, ebp->vec, curs);
	}
	else if (count == 2) {
		EditBonePoint *ebp_a, *ebp_b;
		float head[3], tail[3];
		short headtail = 0;
		
		/* check that the points don't belong to the same bone */
		ebp_a = (EditBonePoint *)points.first;
		ebp_b = ebp_a->next;
		
		if (((ebp_a->head_owner == ebp_b->tail_owner) && (ebp_a->head_owner != NULL)) ||
		    ((ebp_a->tail_owner == ebp_b->head_owner) && (ebp_a->tail_owner != NULL)))
		{
			BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
			BLI_freelistN(&points);
			return OPERATOR_CANCELLED;
		}
		
		/* find which one should be the 'head' */
		if ((ebp_a->head_owner && ebp_b->head_owner) || (ebp_a->tail_owner && ebp_b->tail_owner)) {
			/* use active, nice predictable */
			if (arm->act_edbone && ELEM(arm->act_edbone, ebp_a->head_owner, ebp_a->tail_owner)) {
				headtail = 1;
			}
			else if (arm->act_edbone && ELEM(arm->act_edbone, ebp_b->head_owner, ebp_b->tail_owner)) {
				headtail = 2;
			}
			else {
				/* rule: whichever one is closer to 3d-cursor */
				float curs[3];
				float dist_sq_a, dist_sq_b;

				/* get cursor location */
				invert_m4_m4(obedit->imat, obedit->obmat);
				mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));

				/* get distances */
				dist_sq_a = len_squared_v3v3(ebp_a->vec, curs);
				dist_sq_b = len_squared_v3v3(ebp_b->vec, curs);

				/* compare distances - closer one therefore acts as direction for bone to go */
				headtail = (dist_sq_a < dist_sq_b) ? 2 : 1;
			}
		}
		else if (ebp_a->head_owner) {
			headtail = 1;
		}
		else if (ebp_b->head_owner) {
			headtail = 2;
		}
		
		/* assign head/tail combinations */
		if (headtail == 2) {
			copy_v3_v3(head, ebp_a->vec);
			copy_v3_v3(tail, ebp_b->vec);
		}
		else if (headtail == 1) {
			copy_v3_v3(head, ebp_b->vec);
			copy_v3_v3(tail, ebp_a->vec);
		}
		
		/* add new bone and parent it to the appropriate end */
		if (headtail) {
			newbone = add_points_bone(obedit, head, tail);
			
			/* do parenting (will need to set connected flag too) */
			if (headtail == 2) {
				/* ebp tail or head - tail gets priority */
				if (ebp_a->tail_owner)
					newbone->parent = ebp_a->tail_owner;
				else
					newbone->parent = ebp_a->head_owner;
			}
			else {
				/* ebp_b tail or head - tail gets priority */
				if (ebp_b->tail_owner)
					newbone->parent = ebp_b->tail_owner;
				else
					newbone->parent = ebp_b->head_owner;
			}

			/* don't set for bone connecting two head points of bones */
			if (ebp_a->tail_owner || ebp_b->tail_owner) {
				newbone->flag |= BONE_CONNECTED;
			}
		}
	}
	else {
		/* FIXME.. figure out a method for multiple bones */
		BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count);
		BLI_freelistN(&points);
		return OPERATOR_CANCELLED;
	}

	if (newbone) {
		ED_armature_deselect_all(obedit);
		arm->act_edbone = newbone;
		newbone->flag |= BONE_TIPSEL;
	}
	
	/* updates */
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
	
	/* free points */
	BLI_freelistN(&points);
	
	return OPERATOR_FINISHED;
}