1) Removed old annoyance in adding armature or bones.

- Add Armature or Bone (SHIFT+A) now adds by default a single Bone, view
  aligned and of unit-size 1.
- Then use E-key (extrude) to draw chains, this option now doesn't popup
  the "OK" requester anymore, so works fast
- Another new method is using CTRL+click to add Bones

This makes it working identical to the other edit modes in Blender. The old
modal loop for drawing bones just wasn't working well either.

Related to this; have a real set of useful Armature primitives?

2) Removed event REMAKEALLIPO, which was added in NaN days for testing, and
proved to be extremely slow. Code is moved now to editnla.c.
Thanks Tom Hendrick to pointing to this nasty buggy feature!
This commit is contained in:
2005-07-19 10:06:57 +00:00
parent 1baf64cd45
commit 8fa42457ca
7 changed files with 214 additions and 345 deletions

View File

@@ -81,7 +81,7 @@ void apply_rot_armature (struct Object *ob, float mat[3][3]);
void clear_armature(struct Object *ob, char mode);
void delete_armature(void);
void deselectall_armature(void);
void deselectall_armature(int toggle);
void deselectall_posearmature (int test);
void draw_armature(struct Object *ob, int dt);
void extrude_armature(void);

View File

@@ -42,7 +42,6 @@ struct SpaceOops;
#define REMAKEIPO 1
#define OOPS_TEST 2
#define REMAKEALLIPO 3 /* Reevan's ipo fixing test */
#define BUT_HORIZONTAL 1
#define BUT_VERTICAL 2

View File

@@ -359,12 +359,8 @@ void join_armature(void)
if(okee("Join selected armatures")==0) return;
/* Put the active armature into editmode and join the bones from the other one*/
#if 1
enter_editmode();
#else
baselist.first=baselist.last=0;
make_boneList(&baselist, &((bArmature*)ob->data)->bonebase, NULL);
#endif
for (base=FIRSTBASE; base; base=nextbase) {
nextbase = base->next;
@@ -416,13 +412,8 @@ void join_armature(void)
curbone->roll +=M_PI;
}
#if 1
BLI_remlink(&eblist, curbone);
BLI_addtail(&G.edbo, curbone);
#else
BLI_remlink(&eblist, curbone);
BLI_addtail(&baselist, curbone);
#endif
}
free_and_unlink_base(base);
@@ -430,14 +421,7 @@ void join_armature(void)
}
}
#if 1
exit_editmode(1);
#else
editbones_to_armature(&baselist, ob);
if (baselist.first){
BLI_freelistN (&baselist);
}
#endif
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWOOPS, 0);
@@ -875,8 +859,7 @@ void mouse_armature(void)
if (nearBone) {
if (!(G.qual & LR_SHIFTKEY)) {
nearBone->flag |= BONE_TIPSEL; // fake, but deselectall toggles
deselectall_armature();
deselectall_armature(0);
}
/* by definition the non-root non-IK bones have no root point drawn,
@@ -994,22 +977,22 @@ void load_editArmature(void)
}
void deselectall_armature(void)
/* Actually, it toggles selection, deselecting
everything if anything is selected */
void deselectall_armature(int toggle)
{
EditBone *eBone;
int sel=1;
if(toggle) {
/* Determine if there are any selected bones
And therefore whether we are selecting or deselecting */
for (eBone=G.edbo.first;eBone;eBone=eBone->next){
if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)){
sel=0;
break;
};
};
}
}
}
else sel= 0;
/* Set the flags */
for (eBone=G.edbo.first;eBone;eBone=eBone->next){
@@ -1017,7 +1000,8 @@ everything if anything is selected */
eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
else
eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
};
}
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWBUTSOBJECT, 0);
@@ -1127,72 +1111,17 @@ void undo_push_armature(char *name)
/* **************** END EditMode stuff ********************** */
/* *************** Adding stuff in editmode *************** */
static void add_bone_input (Object *ob)
/*
FUNCTION:
Creates a bone chain under user input.
As the user clicks to accept each bone,
a new bone is started as the child and IK
child of the previous bone. Pressing ESC
cancels the current bone and leaves bone
adding mode.
*/
/* default bone add, returns it selected, but without tail set */
static EditBone *add_editbone(void)
{
float *cursLoc, cent[3], dx, dy;
float mat[3][3], curs[3], cmat[3][3], imat[3][3], rmat[4][4], itmat[4][4];
short xo, yo, mval[2], mvalo[2], afbreek=0, drawall;
short val;
float restmat[4][4], tempVec[4];
EditBone *bone;
EditBone *parent;
unsigned short event;
float angle, scale;
float length, lengths;
float newEnd[4];
int addbones=1;
float dvec[3], dvecp[3];
EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
cursLoc= give_cursor();
VECCOPY (curs,cursLoc);
G.moving= G_TRANSFORM_EDIT;
while (addbones>0){
afbreek=0;
/* Create an inverse matrix */
Mat3CpyMat4(mat, G.obedit->obmat);
VECCOPY(cent, curs);
cent[0]-= G.obedit->obmat[3][0];
cent[1]-= G.obedit->obmat[3][1];
cent[2]-= G.obedit->obmat[3][2];
Mat3CpyMat4(imat, G.vd->viewmat);
Mat3MulVecfl(imat, cent);
Mat3MulMat3(cmat, imat, mat);
Mat3Inv(imat,cmat);
/* Create a temporary bone */
bone= MEM_callocN(sizeof(EditBone), "eBone");
/* If we're the child of something, set that up now */
if (addbones>1){
parent=G.edbo.last;
bone->parent=parent;
bone->flag|=BONE_IK_TOPARENT;
}
BLI_addtail(&G.edbo, bone);
strcpy (bone->name,"Bone");
unique_editbone_name (bone->name);
BLI_addtail(&G.edbo, bone);
bone->flag |= (BONE_SELECTED);
deselectall_armature();
bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
bone->weight= 1.0F;
bone->dist= 1.0F;
bone->xwidth= 0.1;
@@ -1202,120 +1131,33 @@ static void add_bone_input (Object *ob)
bone->segments= 1;
bone->boneclass = BONE_SKINNABLE;
/* Project cursor center to screenspace. */
getmouseco_areawin(mval);
xo= mvalo[0]= mval[0];
yo= mvalo[1]= mval[1];
window_to_3d(dvecp, xo, yo);
drawall= 2;
while (1) {
getmouseco_areawin(mval);
window_to_3d(dvec, mval[0], mval[1]);
scale=1000;
dx= ((float)mval[0]-(float)xo)*scale;
dy= ((float)mval[1]-(float)yo)*scale;
/* Calc bone length*/
lengths= sqrt((dx*dx)+(dy*dy));
length = sqrt(((dvec[0]-dvecp[0])*(dvec[0]-dvecp[0]))+((dvec[1]-dvecp[1])*(dvec[1]-dvecp[1]))+((dvec[2]-dvecp[2])*(dvec[2]-dvecp[2])));
/* Find rotation around screen normal */
if (lengths>0.0F) {
angle= acos(dy/lengths);
if (dx<0.0F)
angle*= -1.0F;
return bone;
}
else angle= 0.0F;
/* FIXME: Is there a blender-defined way of making rot and trans matrices? */
rmat[0][0]= cos (angle);
rmat[0][1]= -sin (angle);
rmat[0][2]= 0.0F;
rmat[0][3]= 0.0F;
rmat[1][0]= sin (angle);
rmat[1][1]= cos (angle);
rmat[1][2]= 0.0F;
rmat[1][3]= 0.0F;
rmat[2][0]= 0.0F;
rmat[2][1]= 0.0F;
rmat[2][2]= 1.0F;
rmat[2][3]= 0.0F;
rmat[3][0]= cent[0];
rmat[3][1]= cent[1];
rmat[3][2]= cent[2];
rmat[3][3]= 1.0F;
static void add_primitive_bone(Object *ob)
{
float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
EditBone *bone;
/* Rotate object's inversemat by the bone's rotation
to get the coordinate space of the bone */
Mat4CpyMat3 (itmat, imat);
Mat4MulMat4 (restmat, rmat, itmat);
VECCOPY (curs, give_cursor());
/* Find the bone head */
tempVec[0]=0; tempVec[1]=0.0F; tempVec[2]=0.0F; tempVec[3]=1.0F;
Mat4MulVec4fl (restmat, tempVec);
VECCOPY (bone->head, tempVec);
/* Get inverse point for head and orientation for tail */
Mat4Invert(G.obedit->imat, G.obedit->obmat);
Mat4MulVecfl(G.obedit->imat, curs);
/* Find the bone tail */
tempVec[0]=0; tempVec[1]=length; tempVec[2]=0.0F; tempVec[3]=1.0F;
Mat4MulVec4fl (restmat, tempVec);
VECCOPY (bone->tail, tempVec);
Mat3CpyMat4(obmat, G.vd->viewmat);
Mat3CpyMat4(viewmat, G.obedit->obmat);
Mat3MulMat3(totmat, obmat, viewmat);
Mat3Inv(imat, totmat);
/* IF we're a child of something, add the parents' translates */
deselectall_armature(0);
/* Offset of child is new cursor*/
/* Create a bone */
bone= add_editbone();
bone->flag |= BONE_ACTIVE;
VECCOPY (newEnd,bone->tail); newEnd[3]=1;
/* only draw if... */
if(drawall) {
drawall--; // draw twice to have 2 identical buffers
force_draw_all(1);
}
else if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
mvalo[0]= mval[0];
mvalo[1]= mval[1];
force_draw(1);
}
else PIL_sleep_ms(10);
while(qtest()) {
event= extern_qread(&val);
if(val) {
switch(event) {
case ESCKEY:
case RIGHTMOUSE:
BLI_freelinkN (&G.edbo,bone);
afbreek=1;
addbones=0;
break;
case LEFTMOUSE:
case MIDDLEMOUSE:
case SPACEKEY:
case RETKEY:
afbreek= 1;
Mat4MulVec4fl (G.obedit->obmat,newEnd);
curs[0]=newEnd[0];
curs[1]=newEnd[1];
curs[2]=newEnd[2];
addbones++;
break;
} /* End of case*/
} /* End of if (val)*/
if(afbreek) break;
} /* Endd of Qtest loop */
if(afbreek) break;
}/* End of positioning loop (while)*/
} /* End of bone adding loop*/
countall(); // flushes selection!
G.moving= 0;
VECCOPY(bone->head, curs);
VecAddf(bone->tail, bone->head, imat[1]); // bone with unit length 1
}
@@ -1344,11 +1186,8 @@ void add_primitiveArmature(int type)
setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
}
switch (type){
default:
add_bone_input (G.obedit);
break;
};
/* no primitive support yet */
add_primitive_bone(G.obedit);
countall(); // flushes selection!
@@ -1356,6 +1195,133 @@ void add_primitiveArmature(int type)
BIF_undo_push("Add primitive");
}
/* the ctrl-click method */
void addvert_armature(void)
{
EditBone *ebone, *newbone;
float *curs, mat[3][3],imat[3][3];
TEST_EDITARMATURE;
/* find the active or selected bone */
for (ebone = G.edbo.first; ebone; ebone=ebone->next)
if(ebone->flag & BONE_ACTIVE) break;
if(ebone==NULL) return;
deselectall_armature(0);
newbone= add_editbone();
newbone->flag |= BONE_ACTIVE;
VECCOPY(newbone->head, ebone->tail);
curs= give_cursor();
VECCOPY(newbone->tail, curs);
VecSubf(newbone->tail, newbone->tail, G.obedit->obmat[3]);
Mat3CpyMat4(mat, G.obedit->obmat);
Mat3Inv(imat, mat);
Mat3MulVecfl(imat, newbone->tail);
countall();
BIF_undo_push("Add Bone");
allqueue(REDRAWVIEW3D, 0);
while(get_mbut()&R_MOUSE);
}
void adduplicate_armature(void)
{
EditBone *eBone = NULL;
EditBone *curBone;
EditBone *firstDup=NULL; /* The beginning of the duplicated bones in the edbo list */
countall(); // flushes selection!
/* Find the selected bones and duplicate them as needed */
for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){
if (curBone->flag & BONE_SELECTED){
eBone=MEM_callocN(sizeof(EditBone), "addup_editbone");
eBone->flag |= BONE_SELECTED;
/* Copy data from old bone to new bone */
memcpy (eBone, curBone, sizeof(EditBone));
curBone->temp = eBone;
eBone->temp = curBone;
unique_editbone_name (eBone->name);
BLI_addtail (&G.edbo, eBone);
if (!firstDup)
firstDup=eBone;
/* Lets duplicate the list of constraits that the
* current bone has.
*/
/* temporal removed (ton) */
}
}
if (eBone){
/* Fix the head and tail */
if (eBone->parent && !eBone->parent->flag & BONE_SELECTED){
VecSubf (eBone->tail, eBone->tail, eBone->head);
VecSubf (eBone->head, eBone->head, eBone->head);
}
}
/* Run though the list and fix the pointers */
for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){
if (curBone->flag & BONE_SELECTED){
eBone=(EditBone*) curBone->temp;
/* If this bone has no parent,
Set the duplicate->parent to NULL
*/
if (!curBone->parent){
eBone->parent = NULL;
}
/* If this bone has a parent that IS selected,
Set the duplicate->parent to the curBone->parent->duplicate
*/
else if (curBone->parent->flag & BONE_SELECTED){
eBone->parent=(EditBone*) curBone->parent->temp;
}
/* If this bone has a parent that IS not selected,
Set the duplicate->parent to the curBone->parent
*/
else {
eBone->parent=(EditBone*) curBone->parent;
eBone->flag &= ~BONE_IK_TOPARENT;
}
/* Lets try to fix any constraint subtargets that might
have been duplicated */
/* temporal removed (ton) */
}
}
/* Deselect the old bones and select the new ones */
for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){
curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
}
BIF_TransformSetUndo("Add Duplicate");
initTransform(TFM_TRANSLATION, CTX_NO_PET);
Transform();
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWBUTSOBJECT, 0);
allqueue(REDRAWOOPS, 0);
}
/* *************** END Adding stuff in editmode *************** */
/* *************** Tools in editmode *********** */
@@ -1528,18 +1494,16 @@ void unique_editbone_name (char *name)
void extrude_armature(void)
{
EditBone *newbone, *curbone, *first=NULL, *partest;
int totbone= 0;
TEST_EDITARMATURE;
if(okee("Extrude bone segments")==0) return;
/* Duplicate the necessary bones */
for (curbone = G.edbo.first; ((curbone) && (curbone!=first)); curbone=curbone->next){
if (curbone->flag & (BONE_TIPSEL|BONE_SELECTED)){
totbone++;
newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
VECCOPY (newbone->head, curbone->tail);
VECCOPY (newbone->tail, newbone->head);
newbone->parent = curbone;
@@ -1573,9 +1537,11 @@ void extrude_armature(void)
}
/* Deselect the old bone */
curbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
curbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
}
/* if only one bone, make this one active */
if(totbone==1 && first) first->flag |= BONE_ACTIVE;
/* Transform the endpoints */
countall(); // flushes selection!
@@ -1588,101 +1554,6 @@ void extrude_armature(void)
allqueue(REDRAWOOPS, 0);
}
void addvert_armature(void)
{
/* the ctrl-click method */
}
void adduplicate_armature(void)
{
EditBone *eBone = NULL;
EditBone *curBone;
EditBone *firstDup=NULL; /* The beginning of the duplicated bones in the edbo list */
countall(); // flushes selection!
/* Find the selected bones and duplicate them as needed */
for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){
if (curBone->flag & BONE_SELECTED){
eBone=MEM_callocN(sizeof(EditBone), "addup_editbone");
eBone->flag |= BONE_SELECTED;
/* Copy data from old bone to new bone */
memcpy (eBone, curBone, sizeof(EditBone));
curBone->temp = eBone;
eBone->temp = curBone;
unique_editbone_name (eBone->name);
BLI_addtail (&G.edbo, eBone);
if (!firstDup)
firstDup=eBone;
/* Lets duplicate the list of constraits that the
* current bone has.
*/
/* temporal removed (ton) */
}
}
if (eBone){
/* Fix the head and tail */
if (eBone->parent && !eBone->parent->flag & BONE_SELECTED){
VecSubf (eBone->tail, eBone->tail, eBone->head);
VecSubf (eBone->head, eBone->head, eBone->head);
}
}
/* Run though the list and fix the pointers */
for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){
if (curBone->flag & BONE_SELECTED){
eBone=(EditBone*) curBone->temp;
/* If this bone has no parent,
Set the duplicate->parent to NULL
*/
if (!curBone->parent){
eBone->parent = NULL;
}
/* If this bone has a parent that IS selected,
Set the duplicate->parent to the curBone->parent->duplicate
*/
else if (curBone->parent->flag & BONE_SELECTED){
eBone->parent=(EditBone*) curBone->parent->temp;
}
/* If this bone has a parent that IS not selected,
Set the duplicate->parent to the curBone->parent
*/
else {
eBone->parent=(EditBone*) curBone->parent;
eBone->flag &= ~BONE_IK_TOPARENT;
}
/* Lets try to fix any constraint subtargets that might
have been duplicated */
/* temporal removed (ton) */
}
}
/* Deselect the old bones and select the new ones */
for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next){
curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE);
}
BIF_TransformSetUndo("Add Duplicate");
initTransform(TFM_TRANSLATION, CTX_NO_PET);
Transform();
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWBUTSOBJECT, 0);
allqueue(REDRAWOOPS, 0);
}
/* ***************** Pose tools ********************* */
void clear_armature(Object *ob, char mode)

View File

@@ -802,6 +802,20 @@ void deselect_nlachannel_keys (int test)
}
}
/* very bad call! */
static void recalc_all_ipos(void)
{
Ipo *ipo;
IpoCurve *icu;
/* Go to each ipo */
for (ipo=G.main->ipo.first; ipo; ipo=ipo->id.next){
for (icu = ipo->curve.first; icu; icu=icu->next){
sort_time_ipocurve(icu);
testhandles_ipocurve(icu);
}
}
}
void transform_nlachannel_keys(char mode)
{
@@ -1033,7 +1047,7 @@ void transform_nlachannel_keys(char mode)
}
if(cancel==0) BIF_undo_push("Select all NLA");
allspace(REMAKEALLIPO, 0);
recalc_all_ipos(); // bad
allqueue (REDRAWVIEW3D, 0);
allqueue (REDRAWNLA, 0);
allqueue (REDRAWIPO, 0);
@@ -1083,7 +1097,7 @@ void delete_nlachannel_keys(void)
}
BIF_undo_push("Delete NLA keys");
allspace(REMAKEALLIPO, 0);
recalc_all_ipos(); // bad
allspace(REMAKEIPO,0);
allqueue (REDRAWVIEW3D, 0);
allqueue(REDRAWNLA, 0);

View File

@@ -1034,7 +1034,7 @@ static void do_view3d_select_armaturemenu(void *arg, int event)
borderselect();
break;
case 2: /* Select/Deselect all */
deselectall_armature();
deselectall_armature(1);
break;
}
allqueue(REDRAWVIEW3D, 0);

View File

@@ -1230,8 +1230,7 @@ static int tree_element_active_ebone(TreeElement *te, TreeStoreElem *tselem, int
if(set) {
if(G.qual & LR_SHIFTKEY);
else {
ebone->flag |= BONE_SELECTED; // trick deselectall, it toggles... duhh
deselectall_armature();
deselectall_armature(0);
}
ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL;
// flush to parent?

View File

@@ -1108,7 +1108,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else if(G.obedit->type==OB_LATTICE)
deselectall_Latt();
else if(G.obedit->type==OB_ARMATURE)
deselectall_armature();
deselectall_armature(1); // 1 == toggle
}
else if (G.obpose){
switch (G.obpose->type){
@@ -4805,20 +4805,6 @@ void allspace(unsigned short event, short val)
SpaceLink *sl= sa->spacedata.first;
while(sl) {
switch(event) {
case REMAKEALLIPO:
{
Ipo *ipo;
IpoCurve *icu;
/* Go to each ipo */
for (ipo=G.main->ipo.first; ipo; ipo=ipo->id.next){
for (icu = ipo->curve.first; icu; icu=icu->next){
sort_time_ipocurve(icu);
testhandles_ipocurve(icu);
}
}
}
break;
case REMAKEIPO:
if(sl->spacetype==SPACE_IPO) {
SpaceIpo *si= (SpaceIpo *)sl;