[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [14786] trunk/blender/source/blender/src/ editarmature.c: Separating armatures should now be more stable than it was, but is still too unstable to enable for release.
Joshua Leung
aligorith at gmail.com
Sun May 11 13:53:12 CEST 2008
Revision: 14786
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=14786
Author: aligorith
Date: 2008-05-11 13:53:12 +0200 (Sun, 11 May 2008)
Log Message:
-----------
Separating armatures should now be more stable than it was, but is still too unstable to enable for release. So for now, the old warning stands.
Modified Paths:
--------------
trunk/blender/source/blender/src/editarmature.c
Modified: trunk/blender/source/blender/src/editarmature.c
===================================================================
--- trunk/blender/source/blender/src/editarmature.c 2008-05-11 11:34:39 UTC (rev 14785)
+++ trunk/blender/source/blender/src/editarmature.c 2008-05-11 11:53:12 UTC (rev 14786)
@@ -180,7 +180,7 @@
/* Add children if necessary */
if (curBone->childbase.first)
- make_boneList (list, &curBone->childbase, eBone);
+ make_boneList(list, &curBone->childbase, eBone);
}
}
@@ -600,25 +600,24 @@
float delta[3];
/* Get the premat */
- VecSubf (delta, curbone->tail, curbone->head);
+ VecSubf(delta, curbone->tail, curbone->head);
vec_roll_to_mat3(delta, curbone->roll, temp);
- Mat4MulMat34 (premat, temp, mat);
+ Mat4MulMat34(premat, temp, mat);
Mat4MulVecfl(mat, curbone->head);
Mat4MulVecfl(mat, curbone->tail);
/* Get the postmat */
- VecSubf (delta, curbone->tail, curbone->head);
+ VecSubf(delta, curbone->tail, curbone->head);
vec_roll_to_mat3(delta, curbone->roll, temp);
Mat4CpyMat3(postmat, temp);
/* Find the roll */
- Mat4Invert (imat, premat);
- Mat4MulMat4 (difmat, postmat, imat);
+ Mat4Invert(imat, premat);
+ Mat4MulMat4(difmat, postmat, imat);
curbone->roll -= atan2(difmat[2][0], difmat[2][2]);
-
}
/* Fix Constraints and Other Links to this Bone and Armature */
@@ -651,13 +650,16 @@
}
/* Helper function for armature separating - link fixing */
-static void separated_armature_fix_links(Object *origArm, Object *newArm, ListBase *edbo)
+static void separated_armature_fix_links(Object *origArm, Object *newArm)
{
Object *ob;
- bPoseChannel *pchan;
+ bPoseChannel *pchan, *pcha, *pchb;
bConstraint *con;
- EditBone *ebo, *ebn;
+ ListBase *npchans;
+ /* get reference to list of bones in new armature */
+ npchans= &newArm->pose->chanbase;
+
/* let's go through all objects in database */
for (ob= G.main->object.first; ob; ob= ob->id.next) {
/* do some object-type specific things */
@@ -675,27 +677,21 @@
for (ct= targets.first; ct; ct= ct->next) {
/* any targets which point to original armature are redirected to the new one only if:
* - the target isn't the original armature itself
- * - the target is one of the bones which were moved into newArm
+ * - the target is one that can be found in newArm
*/
if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
- for (ebo=edbo->first, ebn=edbo->last; ebo && ebn; ebo=ebo->next, ebn=ebn->prev) {
+ for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
/* check if either one matches */
- if ( (strcmp(ebo->name, ct->subtarget)==0) ||
- (strcmp(ebn->name, ct->subtarget)==0) )
+ if ( (strcmp(pcha->name, ct->subtarget)==0) ||
+ (strcmp(pchb->name, ct->subtarget)==0) )
{
ct->tar= newArm;
- printf("arm = '%s' pchan = '%s', ebo = '%s', YES \n", ob->id.name+2, pchan->name, ebo->name);
- printf("arm = '%s' pchan = '%s', ebn = '%s', YES \n", ob->id.name+2, pchan->name, ebn->name);
break;
}
- else {
- printf("arm = '%s' pchan = '%s', ebo = '%s', NOT\n", ob->id.name+2, pchan->name, ebo->name);
- printf("arm = '%s' pchan = '%s', ebn = '%s', NOT \n", ob->id.name+2, pchan->name, ebn->name);
- }
/* check if both ends have met (to stop checking) */
- if (ebo == ebn) break;
- }
+ if (pcha == pchb) break;
+ }
}
}
@@ -723,17 +719,17 @@
* - the target is one of the bones which were moved into newArm
*/
if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) {
- for (ebo=edbo->first, ebn=edbo->last; ebo && ebn; ebo=ebo->next, ebn=ebn->prev) {
+ for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
/* check if either one matches */
- if ( (strcmp(ebo->name, ct->subtarget)==0) ||
- (strcmp(ebn->name, ct->subtarget)==0) )
+ if ( (strcmp(pcha->name, ct->subtarget)==0) ||
+ (strcmp(pchb->name, ct->subtarget)==0) )
{
ct->tar= newArm;
break;
}
/* check if both ends have met (to stop checking) */
- if (ebo == ebn) break;
+ if (pcha == pchb) break;
}
}
}
@@ -749,34 +745,86 @@
/* Is object parented to a bone of this src armature? */
if (ob->partype==PARBONE) {
/* bone name in object */
- for (ebo=edbo->first, ebn=edbo->last; ebo && ebn; ebo=ebo->next, ebn=ebn->prev) {
+ for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) {
/* check if either one matches */
- if ( (strcmp(ebo->name, ob->parsubstr)==0) ||
- (strcmp(ebn->name, ob->parsubstr)==0) )
+ if ( (strcmp(pcha->name, ob->parsubstr)==0) ||
+ (strcmp(pchb->name, ob->parsubstr)==0) )
{
ob->parent= newArm;
break;
}
/* check if both ends have met (to stop checking) */
- if (ebo == ebn) break;
+ if (pcha == pchb) break;
}
}
}
}
}
+/* 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
+ */
+static void separate_armature_bones (Object *ob, short sel)
+{
+ ListBase edbo = {NULL, NULL};
+ bArmature *arm= (bArmature *)ob->data;
+ bPoseChannel *pchan, *pchann;
+ EditBone *curbone;
+
+ /* make local set of editbones to manipulate here */
+ make_boneList(&edbo, &arm->bonebase, NULL);
+
+ /* 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(&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= 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 editbones_to_armature */
+ 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 */
+ if (pchan->path) MEM_freeN(pchan->path);
+ free_constraints(&pchan->constraints);
+
+ /* get rid of unneeded bone */
+ BLI_freelinkN(&edbo, curbone);
+ BLI_freelinkN(&ob->pose->chanbase, pchan);
+ }
+ }
+
+ /* exit editmode (recalculates pchans too) */
+ editbones_to_armature(&edbo, ob);
+ BLI_freelistN(&edbo);
+}
+
void separate_armature (void)
{
- EditBone *ebo, *ebn;
- Object *oldob;
- Base *base, *oldbase;
+ Object *oldob, *newob;
+ Base *base, *oldbase, *newbase;
bArmature *arm;
- ListBase edbo = {NULL, NULL};
- // 31Mar08 - Aligorith:
- // this tool is currently not ready for production use, as it will still
- // crash in some cases, and also constraint relinking isn't working yet
+ // 31 Mar 08 \ 11 May 08 - Aligorith:
+ // currently, this is still too unstable to be enabled for general consumption.
// remove the following two lines to test this tool... you have been warned!
okee("Not implemented (WIP)");
return;
@@ -788,77 +836,58 @@
arm= G.obedit->data;
- /* we are going to trick everything as follows:
- * 1. duplicate base: this is the new one, remember old pointer
- * 2. set aside all NOT selected bones
- * 3. load_editArmature(): this will be the new base
- * 4. freelist and restore old armature
+ /* we are going to do this as follows (unlike every other instance of separate):
+ * 1. exit editmode for active armature/base. Take note of what this is.
+ * 2. duplicate base - BASACT is the new one now
+ * 3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc
+ * 4. fix constraint links
+ * 5. make original armature active and enter editmode
*/
- /* only edit-base selected */
+ /* 1) only edit-base selected */
base= FIRSTBASE;
- while(base) {
- if(base->lay & G.vd->lay) {
- if(base->object==G.obedit) base->flag |= 1;
+ for (base= FIRSTBASE; base; base= base->next) {
+ if (base->lay & G.vd->lay) {
+ if (base->object==G.obedit) base->flag |= 1;
else base->flag &= ~1;
}
- base= base->next;
}
-
- /* set aside: everything that is not selected */
- for (ebo= G.edbo.first; ebo; ebo= ebn) {
- ebn= ebo->next;
-
- /* remove from original, and move to duplicate if not-selected */
- if ((ebo->flag & BONE_SELECTED)==0) {
- EditBone *curbone;
-
- /* need to make sure children don't still refer to this only if they are selected
- * - potentially slow O(n*n) situation here...
- */
- for (curbone= G.edbo.first; curbone; curbone=curbone->next) {
- if ((curbone->parent == ebo) && (curbone->flag & BONE_SELECTED)) {
- curbone->parent= ebo->parent;
- curbone->flag &= ~BONE_CONNECTED;
- }
- }
-
- BLI_remlink(&G.edbo, ebo);
- BLI_addtail(&edbo, ebo);
- }
- }
-
+
+ /* 1) store starting settings and exit editmode */
oldob= G.obedit;
oldbase= BASACT;
-
- adduplicate(1, 0); /* no transform and zero so do get a linked dupli */
- G.obedit= BASACT->object; /* basact is set in adduplicate() */
+ load_editArmature();
+ free_editArmature();
- G.obedit->data= copy_armature(arm);
- /* because new armature is a copy: reduce user count */
- arm->id.us--;
+ /* 2) duplicate base */
+ adduplicate(1, USER_DUP_ARM); /* no transform and zero so do get a linked dupli */
- load_editArmature();
+ newbase= BASACT; /* basact is set in adduplicate() */
+ newob= newbase->object;
+ newbase->flag &= ~SELECT;
- BASACT->flag &= ~SELECT;
- /* fix links before depsgraph flushes */ // err... or after?
- printf("oldob = %p, obact = %p \n", oldob, G.obedit);
- separated_armature_fix_links(oldob, G.obedit, &G.edbo);
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list