Exemplo n.º 1
0
static int pose_de_select_all_exec(bContext *C, wmOperator *op)
{
	int action = RNA_enum_get(op->ptr, "action");
	
	Scene *scene = CTX_data_scene(C);
	Object *ob = ED_object_context(C);
	bArmature *arm = ob->data;
	int multipaint = scene->toolsettings->multipaint;

	if (action == SEL_TOGGLE) {
		action = CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
	}
	
	/*	Set the flags */
	CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones)
	{
		/* select pchan only if selectable, but deselect works always */
		switch (action) {
			case SEL_SELECT:
				if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
					pchan->bone->flag |= BONE_SELECTED;
				break;
			case SEL_DESELECT:
				pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
				break;
			case SEL_INVERT:
				if (pchan->bone->flag & BONE_SELECTED) {
					pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
				}
				else if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
					pchan->bone->flag |= BONE_SELECTED;
				}
				break;
		}
	}
	CTX_DATA_END;

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
	
	/* weightpaint or mask modifiers need depsgraph updates */
	if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) {
		DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	}

	return OPERATOR_FINISHED;
}
static int armature_de_select_all_exec(bContext *C, wmOperator *op)
{
	int action = RNA_enum_get(op->ptr, "action");

	if (action == SEL_TOGGLE) {
		action = SEL_SELECT;
		/* Determine if there are any selected bones
		 * And therefore whether we are selecting or deselecting */
		if (CTX_DATA_COUNT(C, selected_bones) > 0)
			action = SEL_DESELECT;
	}
	
	/*	Set the flags */
	CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
	{
		/* ignore bone if selection can't change */
		if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
			switch (action) {
				case SEL_SELECT:
					ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
					if (ebone->parent)
						ebone->parent->flag |= (BONE_TIPSEL);
					break;
				case SEL_DESELECT:
					ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
					break;
				case SEL_INVERT:
					if (ebone->flag & BONE_SELECTED) {
						ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
					}
					else {
						ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
						if (ebone->parent)
							ebone->parent->flag |= (BONE_TIPSEL);
					}
					break;
			}
		}
	}
	CTX_DATA_END;

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 3
0
static int pose_de_select_all_exec(bContext *C, wmOperator *op)
{
	int action = RNA_enum_get(op->ptr, "action");
	
	Scene *scene = CTX_data_scene(C);
	Object *ob = ED_object_context(C);
	bArmature *arm = ob->data;
	int multipaint = scene->toolsettings->multipaint;

	if (action == SEL_TOGGLE) {
		action = CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
	}
	
	/*	Set the flags */
	CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones)
	{
		pose_do_bone_select(pchan, action);
	}
Exemplo n.º 4
0
/* only editmode! */
static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
	bArmature *arm;
	EditBone *curBone, *ebone_next;
	Object *obedit = CTX_data_edit_object(C);
	bool changed = false;
	arm = obedit->data;

	/* cancel if nothing selected */
	if (CTX_DATA_COUNT(C, selected_bones) == 0)
		return OPERATOR_CANCELLED;

	armature_select_mirrored(arm);

	BKE_pose_channels_remove(obedit, armature_delete_ebone_cb, arm);

	for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
		ebone_next = curBone->next;
		if (arm->layer & curBone->layer) {
			if (curBone->flag & BONE_SELECTED) {
				if (curBone == arm->act_edbone) arm->act_edbone = NULL;
				ED_armature_ebone_remove(arm, curBone);
				changed = true;
			}
		}
	}

	if (!changed)
		return OPERATOR_CANCELLED;

	ED_armature_edit_sync_selection(arm->edbo);
	BKE_pose_tag_recalc(CTX_data_main(C), obedit->pose);

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);

	return OPERATOR_FINISHED;
}
Exemplo n.º 5
0
/**
 * near duplicate of #armature_duplicate_selected_exec,
 * except for parenting part (keep in sync)
 */
static int armature_symmetrize_exec(bContext *C, wmOperator *op)
{
	bArmature *arm;
	EditBone *ebone_iter;
	EditBone *ebone_first_dupe = NULL;  /* The beginning of the duplicated mirrored bones in the edbo list */

	Object *obedit = CTX_data_edit_object(C);
	const int direction = RNA_enum_get(op->ptr, "direction");
	const int axis = 0;

	arm = obedit->data;

	/* cancel if nothing selected */
	if (CTX_DATA_COUNT(C, selected_bones) == 0)
		return OPERATOR_CANCELLED;

	ED_armature_sync_selection(arm->edbo); // XXX why is this needed?

	preEditBoneDuplicate(arm->edbo);

	/* Select mirrored bones */
	for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
		if (EBONE_VISIBLE(arm, ebone_iter) &&
		    (ebone_iter->flag & BONE_SELECTED))
		{
			char name_flip[MAX_VGROUP_NAME];

			BKE_deform_flip_side_name(name_flip, ebone_iter->name, false);

			if (STREQ(name_flip, ebone_iter->name)) {
				/* if the name matches, we don't have the potential to be mirrored, just skip */
				ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
			}
			else {
				EditBone *ebone = ED_armature_bone_find_name(arm->edbo, name_flip);

				if (ebone) {
					if ((ebone->flag & BONE_SELECTED) == 0) {
						/* simple case, we're selected, the other bone isn't! */
						ebone_iter->temp.ebone = ebone;
					}
					else {
						/* complicated - choose which direction to copy */
						float axis_delta;

						axis_delta = ebone->head[axis] - ebone_iter->head[axis];
						if (axis_delta == 0.0f) {
							axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
						}

						if (axis_delta == 0.0f) {
							/* both mirrored bones exist and point to eachother and overlap exactly.
							 *
							 * in this case theres no well defined solution, so de-select both and skip.
							 */
							ebone->flag      &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
							ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
						}
						else {
							EditBone *ebone_src, *ebone_dst;
							if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
								ebone_src = ebone;
								ebone_dst = ebone_iter;
							}
							else {
								ebone_src = ebone_iter;
								ebone_dst = ebone;
							}

							ebone_src->temp.ebone = ebone_dst;
							ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
						}
					}
				}
			}
		}
	}

	/*	Find the selected bones and duplicate them as needed, with mirrored name */
	for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
		if (EBONE_VISIBLE(arm, ebone_iter) &&
		    (ebone_iter->flag & BONE_SELECTED) &&
		    /* will be set if the mirror bone already exists (no need to make a new one) */
		    (ebone_iter->temp.ebone == NULL))
		{
			char name_flip[MAX_VGROUP_NAME];

			BKE_deform_flip_side_name(name_flip, ebone_iter->name, false);

			/* bones must have a side-suffix */
			if (!STREQ(name_flip, ebone_iter->name)) {
				EditBone *ebone;

				ebone = duplicateEditBone(ebone_iter, name_flip, arm->edbo, obedit);

				if (!ebone_first_dupe) {
					ebone_first_dupe = ebone;
				}
			}
		}
	}

	/*	Run through the list and fix the pointers */
	for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
		if (ebone_iter->temp.ebone) {
			/* copy all flags except for ... */
			const int flag_copy = ((int)~0) & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);

			EditBone *ebone = ebone_iter->temp.ebone;

			/* copy flags incase bone is pre-existing data */
			ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy);

			if (ebone_iter->parent == NULL) {
				/* If this bone has no parent,
				 * Set the duplicate->parent to NULL
				 */
				ebone->parent = NULL;
				ebone->flag &= ~BONE_CONNECTED;
			}
			else {
				/* the parent may have been duplicated, if not lookup the mirror parent */
				EditBone *ebone_parent =
				        (ebone_iter->parent->temp.ebone ?
				         ebone_iter->parent->temp.ebone : ED_armature_bone_get_mirrored(arm->edbo, ebone_iter->parent));

				if (ebone_parent == NULL) {
					/* If the mirror lookup failed, (but the current bone has a parent)
					 * then we can assume the parent has no L/R but is a center bone.
					 * So just use the same parent for both.
					 */
					ebone_parent = ebone_iter->parent;
					ebone->flag &= ~BONE_CONNECTED;
				}

				ebone->parent = ebone_parent;
			}

			/* Lets try to fix any constraint subtargets that might
			 * have been duplicated
			 */
			updateDuplicateSubtarget(ebone, arm->edbo, obedit);
		}
	}

	transform_armature_mirror_update(obedit);

	/* Selected bones now have their 'temp' pointer set,
	 * so we don't need this anymore */

	/* Deselect the old bones and select the new ones */
	for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
		if (EBONE_VISIBLE(arm, ebone_iter)) {
			ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
		}
	}

	/* New bones will be selected, but some of the bones may already exist */
	for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
		EditBone *ebone = ebone_iter->temp.ebone;
		if (ebone && EBONE_SELECTABLE(arm, ebone)) {
			ED_armature_ebone_select_set(ebone, true);
		}
	}

	/* correct the active bone */
	if (arm->act_edbone && arm->act_edbone->temp.ebone) {
		arm->act_edbone = arm->act_edbone->temp.ebone;
	}

	postEditBoneDuplicate(arm->edbo, obedit);

	ED_armature_validate_active(arm);

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);

	return OPERATOR_FINISHED;
}
Exemplo n.º 6
0
static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
	bArmature *arm;
	EditBone *ebone_iter;
	EditBone *ebone_first_dupe = NULL;  /* The beginning of the duplicated bones in the edbo list */

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

	/* cancel if nothing selected */
	if (CTX_DATA_COUNT(C, selected_bones) == 0)
		return OPERATOR_CANCELLED;
	
	ED_armature_sync_selection(arm->edbo); // XXX why is this needed?

	preEditBoneDuplicate(arm->edbo);

	/* Select mirrored bones */
	if (arm->flag & ARM_MIRROR_EDIT) {
		for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
			if (EBONE_VISIBLE(arm, ebone_iter) &&
			    (ebone_iter->flag & BONE_SELECTED))
			{
				EditBone *ebone;

				ebone = ED_armature_bone_get_mirrored(arm->edbo, ebone_iter);
				if (ebone) {
					ebone->flag |= BONE_SELECTED;
				}
			}
		}
	}

	
	/* Find the selected bones and duplicate them as needed */
	for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
		if (EBONE_VISIBLE(arm, ebone_iter) &&
		    (ebone_iter->flag & BONE_SELECTED))
		{
			EditBone *ebone;

			ebone = duplicateEditBone(ebone_iter, ebone_iter->name, arm->edbo, obedit);

			if (!ebone_first_dupe) {
				ebone_first_dupe = ebone;
			}
		}
	}

	/* Run though the list and fix the pointers */
	for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
		if (EBONE_VISIBLE(arm, ebone_iter) &&
		    (ebone_iter->flag & BONE_SELECTED))
		{
			EditBone *ebone = ebone_iter->temp.ebone;

			if (!ebone_iter->parent) {
				/* If this bone has no parent,
				 * Set the duplicate->parent to NULL
				 */
				ebone->parent = NULL;
			}
			else if (ebone_iter->parent->temp.ebone) {
				/* If this bone has a parent that was duplicated,
				 * Set the duplicate->parent to the curBone->parent->temp
				 */
				ebone->parent = ebone_iter->parent->temp.ebone;
			}
			else {
				/* If this bone has a parent that IS not selected,
				 * Set the duplicate->parent to the curBone->parent
				 */
				ebone->parent = (EditBone *) ebone_iter->parent;
				ebone->flag &= ~BONE_CONNECTED;
			}

			/* Lets try to fix any constraint subtargets that might
			 * have been duplicated
			 */
			updateDuplicateSubtarget(ebone, arm->edbo, obedit);
		}
	}
	
	/* correct the active bone */
	if (arm->act_edbone && arm->act_edbone->temp.ebone) {
		arm->act_edbone = arm->act_edbone->temp.ebone;
	}

	/* Deselect the old bones and select the new ones */
	for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) {
		if (EBONE_VISIBLE(arm, ebone_iter)) {
			ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
		}
	}

	postEditBoneDuplicate(arm->edbo, obedit);

	ED_armature_validate_active(arm);

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 7
0
static int armature_parent_set_exec(bContext *C, wmOperator *op) 
{
	Object *ob = CTX_data_edit_object(C);
	bArmature *arm = (bArmature *)ob->data;
	EditBone *actbone = CTX_data_active_bone(C);
	EditBone *actmirb = NULL;
	short val = RNA_enum_get(op->ptr, "type");
	
	/* there must be an active bone */
	if (actbone == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
		return OPERATOR_CANCELLED;
	}
	else if (arm->flag & ARM_MIRROR_EDIT) {
		/* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
		 * - 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.
		 */
		actmirb = ED_armature_bone_get_mirrored(arm->edbo, actbone);
		if (actmirb == NULL) 
			actmirb = actbone;
	}
	
	/* if there is only 1 selected bone, we assume that that is the active bone, 
	 * since a user will need to have clicked on a bone (thus selecting it) to make it active
	 */
	if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
		/* When only the active bone is selected, and it has a parent,
		 * connect it to the parent, as that is the only possible outcome. 
		 */
		if (actbone->parent) {
			bone_connect_to_existing_parent(actbone);
			
			if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
				bone_connect_to_existing_parent(actmirb);
		}
	}
	else {
		/* Parent 'selected' bones to the active one
		 * - the context iterator contains both selected bones and their mirrored copies,
		 *   so we assume that unselected bones are mirrored copies of some selected bone
		 * - since the active one (and/or its mirror) will also be selected, we also need 
		 *  to check that we are not trying to operate on them, since such an operation
		 *	would cause errors
		 */
		
		/* parent selected bones to the active one */
		CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
		{
			if (ELEM(ebone, actbone, actmirb) == 0) {
				if (ebone->flag & BONE_SELECTED) 
					bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
				else
					bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val);
			}
		}
		CTX_DATA_END;
	}
	

	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 8
0
/* poll callback for all stroke editing operators */
static int gp_stroke_edit_poll(bContext *C)
{
	/* NOTE: this is a bit slower, but is the most accurate... */
	return CTX_DATA_COUNT(C, editable_gpencil_strokes) != 0;
}