Пример #1
0
/* note: there's a unique_bone_name() too! */
static bool editbone_unique_check(void *arg, const char *name)
{
    struct {
        ListBase *lb;
        void *bone;
    } *data = arg;
    EditBone *dupli = editbone_name_exists(data->lb, name);
    return dupli && dupli != data->bone;
}
Пример #2
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);
}
Пример #3
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;
}
Пример #4
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 = editbone_name_exists(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) {
                        BLI_strncpy(pchan->name, newname, MAXBONENAME);

                        if (ob->pose->chanhash) {
                            GHash *gh = ob->pose->chanhash;

                            /* remove the old hash entry, and replace with the new name */
                            BLI_ghash_remove(gh, oldname, NULL, NULL);
                            BLI_ghash_insert(gh, pchan->name, pchan);
                        }
                    }
                }

                /* 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) {
                if (md->type == eModifierType_Hook) {
                    HookModifierData *hmd = (HookModifierData *)md;

                    /* uses armature, so may use the affected bone name */
                    if (hmd->object && (hmd->object->data == arm)) {
                        if (!strcmp(hmd->subtarget, oldname))
                            BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
                    }
                }
            }
        }

        /* 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);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}