示例#1
0
static int armature_merge_exec(bContext *C, wmOperator *op)
{
	Object *obedit = CTX_data_edit_object(C);
	bArmature *arm = (obedit) ? obedit->data : NULL;
	short type = RNA_enum_get(op->ptr, "type");
	
	/* sanity checks */
	if (ELEM(NULL, obedit, arm))
		return OPERATOR_CANCELLED;
	
	/* for now, there's only really one type of merging that's performed... */
	if (type == 1) {
		/* go down chains, merging bones */
		ListBase chains = {NULL, NULL};
		LinkData *chain, *nchain;
		EditBone *ebo;
		
		armature_tag_select_mirrored(arm);
		
		/* get chains (ends on chains) */
		chains_find_tips(arm->edbo, &chains);
		if (chains.first == NULL) return OPERATOR_CANCELLED;
		
		/* each 'chain' is the last bone in the chain (with no children) */
		for (chain = chains.first; chain; chain = nchain) {
			EditBone *bstart = NULL, *bend = NULL;
			EditBone *bchild = NULL, *child = NULL;
			
			/* temporarily remove chain from list of chains */
			nchain = chain->next;
			BLI_remlink(&chains, chain);
			
			/* only consider bones that are visible and selected */
			for (ebo = chain->data; ebo; child = ebo, ebo = ebo->parent) {
				/* check if visible + selected */
				if (EBONE_VISIBLE(arm, ebo) &&
				    ((ebo->flag & BONE_CONNECTED) || (ebo->parent == NULL)) &&
				    (ebo->flag & BONE_SELECTED) )
				{
					/* set either end or start (end gets priority, unless it is already set) */
					if (bend == NULL) {
						bend = ebo;
						bchild = child;
					}
					else 
						bstart = ebo;
				}
				else {
					/* chain is broken... merge any continous segments then clear */
					if (bstart && bend)
						bones_merge(obedit, bstart, bend, bchild, &chains);
					
					bstart = NULL;
					bend = NULL;
					bchild = NULL;
				}
			}
			
			/* merge from bstart to bend if something not merged */
			if (bstart && bend)
				bones_merge(obedit, bstart, bend, bchild, &chains);
			
			/* put back link */
			BLI_insertlinkbefore(&chains, nchain, chain);
		}
		
		armature_tag_unselect(arm);
		
		BLI_freelistN(&chains);
	}
	
	/* updates */
	ED_armature_sync_selection(arm->edbo);
	WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
	
	return OPERATOR_FINISHED;
}
示例#2
0
static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *ob = CTX_data_edit_object(C);
	bArmature *arm = (bArmature *)ob->data;
	ListBase chains = {NULL, NULL};
	LinkData *chain;

	/* get chains of bones (ends on chains) */
	chains_find_tips(arm->edbo, &chains);
	if (BLI_listbase_is_empty(&chains)) return OPERATOR_CANCELLED;

	/* ensure that mirror bones will also be operated on */
	armature_tag_select_mirrored(arm);

	/* clear BONE_TRANSFORM flags
	 * - used to prevent duplicate/canceling operations from occurring [#34123]
	 * - BONE_DONE cannot be used here as that's already used for mirroring
	 */
	armature_clear_swap_done_flags(arm);

	/* loop over chains, only considering selected and visible bones */
	for (chain = chains.first; chain; chain = chain->next) {
		EditBone *ebo, *child = NULL, *parent = NULL;

		/* loop over bones in chain */
		for (ebo = chain->data; ebo; ebo = parent) {
			/* parent is this bone's original parent
			 *	- we store this, as the next bone that is checked is this one
			 *	  but the value of ebo->parent may change here...
			 */
			parent = ebo->parent;

			/* skip bone if already handled... [#34123] */
			if ((ebo->flag & BONE_TRANSFORM) == 0) {
				/* only if selected and editable */
				if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {
					/* swap head and tail coordinates */
					swap_v3_v3(ebo->head, ebo->tail);

					/* do parent swapping:
					 *	- use 'child' as new parent
					 *	- connected flag is only set if points are coincidental
					 */
					ebo->parent = child;
					if ((child) && equals_v3v3(ebo->head, child->tail))
						ebo->flag |= BONE_CONNECTED;
					else
						ebo->flag &= ~BONE_CONNECTED;

					/* get next bones
					 *	- child will become the new parent of next bone
					 */
					child = ebo;
				}
				else {
					/* not swapping this bone, however, if its 'parent' got swapped, unparent us from it
					 * as it will be facing in opposite direction
					 */
					if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
						ebo->parent = NULL;
						ebo->flag &= ~BONE_CONNECTED;
					}

					/* get next bones
					 *	- child will become new parent of next bone (not swapping occurred,
					 *	  so set to NULL to prevent infinite-loop)
					 */
					child = NULL;
				}

				/* tag as done (to prevent double-swaps) */
				ebo->flag |= BONE_TRANSFORM;
			}
		}
	}

	/* free chains */
	BLI_freelistN(&chains);

	/* clear temp flags */
	armature_clear_swap_done_flags(arm);
	armature_tag_unselect(arm);

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

	return OPERATOR_FINISHED;
}