Patch #6794: Subdivide Multi for Armatures

This patch, by Juho Vepsalainen (BeBraw), introduces subdivide multi functionality for armatures. It lets you specify the number of divisions that selected bones should be divided into. 

I've slightly optimised the code a bit, though the change shouldn't make much of a difference. I've also fixed a minor bug in the menu highlighting, due to duplicate menu event-codes.
This commit is contained in:
Joshua Leung 2007-09-09 11:05:21 +00:00
parent b709e2982f
commit 8ddbd84240
4 changed files with 77 additions and 39 deletions

@ -85,7 +85,7 @@ void deselectall_armature(int toggle, int doundo);
void deselectall_posearmature (struct Object *ob, int test, int doundo); void deselectall_posearmature (struct Object *ob, int test, int doundo);
int draw_armature(struct Base *base, int dt); int draw_armature(struct Base *base, int dt);
void extrude_armature(int forked); void extrude_armature(int forked);
void subdivide_armature(void); void subdivide_armature(int numcuts);
void free_editArmature(void); void free_editArmature(void);
@ -139,3 +139,4 @@ void show_all_armature_bones(void);
#endif #endif

@ -2133,53 +2133,77 @@ void extrude_armature(int forked)
} }
/* context; editmode armature */ /* context; editmode armature */
void subdivide_armature(void) void subdivide_armature(int numcuts)
{ {
bArmature *arm= G.obedit->data; bArmature *arm= G.obedit->data;
EditBone *ebone, *newbone, *tbone, *mbone; EditBone *ebone, *newbone, *tbone, *mbone;
int a; int a, i;
if(numcuts < 1) return;
for (mbone = G.edbo.last; mbone; mbone= mbone->prev) { for (mbone = G.edbo.last; mbone; mbone= mbone->prev) {
if(arm->layer & mbone->layer) { if(arm->layer & mbone->layer) {
if(mbone->flag & BONE_SELECTED) { if(mbone->flag & BONE_SELECTED) {
for(i=numcuts+1; i>1; i--) {
/* take care of mirrored stuff */ /* compute cut ratio first */
for(a=0; a<2; a++) { float cutratio= 1/(float)i;
if(a==0) ebone= mbone; float cutratioI= 1-cutratio;
else {
if(arm->flag & ARM_MIRROR_EDIT) /* take care of mirrored stuff */
ebone= armature_bone_get_mirrored(mbone); for(a=0; a<2; a++) {
else ebone= NULL; float val1[3];
} float val2[3];
if(ebone) { float val3[3];
newbone= MEM_mallocN(sizeof(EditBone), "ebone subdiv");
*newbone = *ebone;
BLI_addtail(&G.edbo, newbone);
VecMidf(newbone->head, ebone->head, ebone->tail); /* try to find mirrored bone on a != 0 */
VECCOPY(newbone->tail, ebone->tail); if(a) {
VECCOPY(ebone->tail, newbone->head); if(arm->flag & ARM_MIRROR_EDIT)
ebone= armature_bone_get_mirrored(mbone);
newbone->rad_head= 0.5*(ebone->rad_head+ebone->rad_tail); else ebone= NULL;
ebone->rad_tail= newbone->rad_head; }
else
newbone->flag |= BONE_CONNECTED; ebone= mbone;
unique_editbone_name (&G.edbo, newbone->name); if(ebone) {
newbone= MEM_mallocN(sizeof(EditBone), "ebone subdiv");
/* correct parent bones */ *newbone = *ebone;
for (tbone = G.edbo.first; tbone; tbone=tbone->next){ BLI_addtail(&G.edbo, newbone);
if(tbone->parent==ebone)
tbone->parent= newbone; /* calculate location of newbone->head */
VECCOPY(val1, ebone->head);
VECCOPY(val2, ebone->tail);
VECCOPY(val3, newbone->head);
val3[0]= val1[0]*cutratio+val2[0]*cutratioI;
val3[1]= val1[1]*cutratio+val2[1]*cutratioI;
val3[2]= val1[2]*cutratio+val2[2]*cutratioI;
VECCOPY(newbone->head, val3);
VECCOPY(newbone->tail, ebone->tail);
VECCOPY(ebone->tail, newbone->head);
newbone->rad_head= 0.5*(ebone->rad_head+ebone->rad_tail);
ebone->rad_tail= newbone->rad_head;
newbone->flag |= BONE_CONNECTED;
unique_editbone_name (&G.edbo, newbone->name);
/* correct parent bones */
for (tbone = G.edbo.first; tbone; tbone=tbone->next){
if(tbone->parent==ebone)
tbone->parent= newbone;
}
newbone->parent= ebone;
} }
newbone->parent= ebone;
} }
} }
} }
} }
} }
BIF_undo_push("Subdivide");
if(numcuts==1) BIF_undo_push("Subdivide");
else BIF_undo_push("Subdivide multi");
} }
/* ***************** Pose tools ********************* */ /* ***************** Pose tools ********************* */

@ -2508,10 +2508,15 @@ void special_editmenu(void)
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
} }
else if(G.obedit->type==OB_ARMATURE) { else if(G.obedit->type==OB_ARMATURE) {
nr= pupmenu("Specials%t|Subdivide %x1|Flip Left-Right Names%x2"); nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Flip Left-Right Names%x3");
if(nr==1) if(nr==1)
subdivide_armature(); subdivide_armature(1);
else if(nr==2) if(nr==2) {
if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
waitcursor(1);
subdivide_armature(numcuts);
}
else if(nr==3)
armature_flip_names(); armature_flip_names();
} }
else if(G.obedit->type==OB_LATTICE) { else if(G.obedit->type==OB_LATTICE) {

@ -3672,6 +3672,8 @@ static uiBlock *view3d_edit_armature_rollmenu(void *arg_unused)
static void do_view3d_edit_armaturemenu(void *arg, int event) static void do_view3d_edit_armaturemenu(void *arg, int event)
{ {
static short numcuts= 2;
switch(event) { switch(event) {
case 0: /* Undo Editing */ case 0: /* Undo Editing */
@ -3700,11 +3702,16 @@ static void do_view3d_edit_armaturemenu(void *arg, int event)
extrude_armature(1); extrude_armature(1);
break; break;
case 12: /* subdivide */ case 12: /* subdivide */
subdivide_armature(); subdivide_armature(1);
break; break;
case 13: /* flip left and right names */ case 13: /* flip left and right names */
armature_flip_names(); armature_flip_names();
break; break;
break;
case 15: /* subdivide multi */
if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
waitcursor(1);
subdivide_armature(numcuts);
} }
allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWVIEW3D, 0);
} }
@ -3774,7 +3781,8 @@ static uiBlock *view3d_edit_armaturemenu(void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide|W, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide|W, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Flip Left & Right Names|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Multi|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Flip Left & Right Names|W, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");