diff options
23 files changed, 1236 insertions, 350 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 229ef7a297b..9c674971bbf 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -78,7 +78,7 @@ void init_armature_deform(struct Object *parent, struct Object *ob); struct bArmature* get_armature (struct Object* ob); struct Bone *get_named_bone (struct bArmature *arm, const char *name); -float dist_to_bone (float vec[3], float b1[3], float b2[3]); +float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, float rad2, float rdist); void where_is_armature (struct bArmature *arm); void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 4f2d1ce3100..317659ade68 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -537,56 +537,74 @@ void init_armature_deform(Object *parent, Object *ob) /* bone defmats are already in the channels, chan_mat */ } -float dist_to_bone (float vec[3], float b1[3], float b2[3]) +/* using vec with dist to bone b1 - b2 */ +float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, float rad2, float rdist) { -/* float dist=0; */ + float dist=0.0f; float bdelta[3]; float pdelta[3]; - float hsqr, a, l; - + float hsqr, a, l, rad; + VecSubf (bdelta, b2, b1); l = Normalise (bdelta); - + VecSubf (pdelta, vec, b1); - + a = bdelta[0]*pdelta[0] + bdelta[1]*pdelta[1] + bdelta[2]*pdelta[2]; hsqr = ((pdelta[0]*pdelta[0]) + (pdelta[1]*pdelta[1]) + (pdelta[2]*pdelta[2])); - + if (a < 0.0F){ - //return 100000; - /* If we're past the end of the bone, do some weird field attenuation thing */ - return ((b1[0]-vec[0])*(b1[0]-vec[0]) +(b1[1]-vec[1])*(b1[1]-vec[1]) +(b1[2]-vec[2])*(b1[2]-vec[2])) ; + /* If we're past the end of the bone, do a spherical field attenuation thing */ + dist= ((b1[0]-vec[0])*(b1[0]-vec[0]) +(b1[1]-vec[1])*(b1[1]-vec[1]) +(b1[2]-vec[2])*(b1[2]-vec[2])) ; + rad= rad1; } else if (a > l){ - //return 100000; - /* If we're past the end of the bone, do some weird field attenuation thing */ - return ((b2[0]-vec[0])*(b2[0]-vec[0]) +(b2[1]-vec[1])*(b2[1]-vec[1]) +(b2[2]-vec[2])*(b2[2]-vec[2])) ; + /* If we're past the end of the bone, do a spherical field attenuation thing */ + dist= ((b2[0]-vec[0])*(b2[0]-vec[0]) +(b2[1]-vec[1])*(b2[1]-vec[1]) +(b2[2]-vec[2])*(b2[2]-vec[2])) ; + rad= rad2; } else { - return (hsqr - (a*a)); + dist= (hsqr - (a*a)); + + if(l!=0.0f) { + rad= a/l; + rad= rad*rad2 + (1.0-rad)*rad1; + } + else rad= rad1; + } + + a= rad*rad; + if(dist < a) + return 1.0f; + else { + l= rad+rdist; + l*= l; + if(rdist==0.0f || dist >= l) + return 0.0f; + else { + a= sqrt(dist)-rad; + return 1.0-( a*a )/( rdist*rdist ); + } } } static float dist_bone_deform(bPoseChannel *pchan, float *vec, float *co) { Bone *bone= pchan->bone; - float dist, fac, ifac; + float fac; float cop[3]; - float bdsqr, contrib=0.0; + float contrib=0.0; if(bone==NULL) return 0.0f; - bdsqr = bone->dist*bone->dist; VECCOPY (cop, co); - dist = dist_to_bone(cop, bone->arm_head, bone->arm_tail); + fac= distfactor_to_bone(cop, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist); - if ((dist) <= bdsqr){ - fac = (dist)/bdsqr; - ifac = 1.0F-fac; + if (fac>0.0){ - ifac*=bone->weight; - contrib= ifac; + fac*=bone->weight; + contrib= fac; if(contrib>0.0) { VECCOPY (cop, co); @@ -594,7 +612,7 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, float *co) Mat4MulVecfl(pchan->chan_mat, cop); VecSubf (cop, cop, co); // Make this a delta from the base position - cop[0]*=ifac; cop[1]*=ifac; cop[2]*=ifac; + cop[0]*=fac; cop[1]*=fac; cop[2]*=fac; VecAddf (vec, vec, cop); } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9859496831f..928820f91fd 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3373,6 +3373,22 @@ static int map_223_keybd_code_to_224_keybd_code(int code) } } +static void bone_version_238(ListBase *lb) +{ + Bone *bone; + + for(bone= lb->first; bone; bone= bone->next) { + if(bone->rad_tail==0.0f && bone->rad_head==0.0f) { + bone->rad_head= 0.25f*bone->length; + bone->rad_tail= 0.1f*bone->length; + + bone->dist-= bone->rad_head; + if(bone->dist<=0.0f) bone->dist= 0.0f; + } + bone_version_238(&bone->childbase); + } +} + static void do_versions(FileData *fd, Library *lib, Main *main) { /* WATCH IT!!!: pointers from libdata have not been converted */ @@ -4854,6 +4870,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if(main->versionfile <= 238) { Lattice *lt; Object *ob; + bArmature *arm; for (lt=main->latt.first; lt; lt=lt->id.next) { if (lt->fu==0.0 && lt->fv==0.0 && lt->fw==0.0) { @@ -4880,6 +4897,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ob->softflag &= ~OB_SB_ENABLE; } } + + for(arm=main->armature.first; arm; arm= arm->id.next) { + bone_version_238(&arm->bonebase); + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 73807dab5dc..6afe0903a21 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -43,7 +43,7 @@ typedef struct EditBone struct EditBone *parent;/* Editbones have a one-way link (i.e. children refer to parents. This is converted to a two-way link for normal bones when leaving editmode. */ - void *temp; /* Used to store temporary data */ + void *temp; /* Used to store temporary data */ char name[32]; float roll; /* Roll along axis. We'll ultimately use the axis/angle method @@ -59,17 +59,14 @@ typedef struct EditBone int flag; int parNr; /* Used for retrieving values from the menu system */ - /* Storage for transformation data used by the posing system. - Maybe a better solution would be to make bones a blenderObject - variant? Or perhaps to use a TOTALLY custom transformation scheme - for pose element, rather than trying to use the existing transObject - system? - */ + float dist, weight; float xwidth, length, zwidth; /* put them in order! transform uses this as scale */ float ease1, ease2; + float rad_head, rad_tail; short boneclass, segments; - + + float oldlength; /* for envelope scaling */ } EditBone; @@ -127,6 +124,10 @@ void armature_bone_rename(struct bArmature *arm, char *oldname, char *newname); void armature_flip_names(void); EditBone *armature_bone_get_mirrored(EditBone *ebo); +void hide_selected_armature_bones(void); +void hide_unselected_armature_bones(void); +void show_all_armature_bones(void); + #define BONESEL_ROOT 0x10000000 #define BONESEL_TIP 0x20000000 #define BONESEL_BONE 0x40000000 diff --git a/source/blender/include/BIF_poseobject.h b/source/blender/include/BIF_poseobject.h index 3b707ad8dcc..ec201437488 100644 --- a/source/blender/include/BIF_poseobject.h +++ b/source/blender/include/BIF_poseobject.h @@ -55,6 +55,8 @@ void free_posebuf(void); void copy_posebuf (void); void paste_posebuf (int flip); +void pose_adds_vgroups(struct Object *meshobj); + void pose_flip_names(void); #endif diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index 4a161181a5c..cff4dea2e14 100755 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -51,6 +51,7 @@ #define TFM_CREASE 13 #define TFM_MIRROR 14 #define TFM_BONESIZE 15 +#define TFM_BONE_ENVELOPE 16 /* TRANSFORM CONTEXTS */ #define CTX_NONE 0 diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 7842d9cbd5f..4e6eaa7150c 100755 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -254,6 +254,9 @@ int Crease(TransInfo *t, short mval[2]); void initBoneSize(TransInfo *t); int BoneSize(TransInfo *t, short mval[2]); +void initBoneEnvelope(TransInfo *t); +int BoneEnvelope(TransInfo *t, short mval[2]); + /*********************** transform_conversions.c ********** */ struct ListBase; void count_bone_select(TransInfo *t, struct ListBase *lb, int do_it); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index f80414312db..7a5d7520fca 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -1,20 +1,12 @@ -/* DNA_action_types.h May 2001 - * - * support for the "action" datatype - * - * Reevan McKay - * +/* * $Id$ * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -28,9 +20,10 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * + * Contributor(s): Original design: Reevan McKay * Contributor(s): Full recode, Ton Roosendaal, Crete 2005 * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ***** END GPL LICENSE BLOCK ***** */ diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 819b2843eda..013b42876a1 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -49,7 +49,7 @@ typedef struct Bone { ListBase childbase; /* Children */ char name[32]; /* Name of the bone - must be unique within the armature */ - float roll, length; /* roll is input for editmode, length calculated */ + float roll; /* roll is input for editmode, length calculated */ float head[3]; float tail[3]; /* head/tail and roll in Bone Space */ float bone_mat[3][3]; /* rotation derived from head/tail/roll */ @@ -60,9 +60,10 @@ typedef struct Bone { float arm_tail[3]; /* head/tail and roll in Armature Space (rest pos) */ float arm_mat[4][4]; /* matrix: (bonemat(b)+head(b))*arm_mat(b-1), rest pos*/ - float dist, weight; /* dist, weight: for non-deformgroup deforms */ - float xwidth, zwidth; /* width: for block bones */ - float ease1, ease2; /* length of bezier handles */ + float dist, weight; /* dist, weight: for non-deformgroup deforms */ + float xwidth, length, zwidth; /* width: for block bones. keep in this order, transform! */ + float ease1, ease2; /* length of bezier handles */ + float rad_head, rad_tail; /* radius for head/tail sphere, defining deform as well */ float size[3]; /* patch for upward compat, UNUSED! */ short boneclass; @@ -99,6 +100,7 @@ typedef struct bArmature { #define ARM_OCTA 0 #define ARM_LINE 1 #define ARM_B_BONE 2 +#define ARM_ENVELOPE 3 /* bone->flag */ @@ -109,13 +111,16 @@ typedef struct bArmature { #define BONE_TRANSFORM 8 #define BONE_IK_TOPARENT 16 /* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */ -#define BONE_HIDDEN 64 + /* hidden Bones when drawing Posechannels */ +#define BONE_HIDDEN_P 64 /* For detecting cyclic dependancies */ #define BONE_DONE 128 /* active is on mouse clicks only */ #define BONE_ACTIVE 256 /* No parent rotation or scale */ #define BONE_HINGE 512 + /* hidden Bones when drawing Armature Editmode */ +#define BONE_HIDDEN_A 1024 /* bone->flag bits */ #define BONE_IK_TOPARENTBIT 4 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index e69c646579c..3ad4742730c 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -448,28 +448,28 @@ static void editing_panel_mesh_type(Object *ob, Mesh *me) if(me->medge) val= 1.0; else val= 0.0; uiDefBut(block, LABEL, 0, "Edges", 10,70,70,20, 0, val, 0, 0, 0, ""); if(me->medge==NULL) { - uiDefBut(block, BUT, B_MAKEEDGES, "Make", 80,70,84,19, 0, 0, 0, 0, 0, "Adds edges data to active Mesh object, enables creases/seams and faster wireframe draw"); + uiDefBut(block, BUT, B_MAKEEDGES, "Make", 80,70,84,19, 0, 0, 0, 0, 0, "Adds edges data to active Mesh, enables creases/seams and faster wireframe draw"); } - else uiDefBut(block, BUT, B_DELEDGES, "Delete", 80,70,84,19, 0, 0, 0, 0, 0, "Deletes edges data from active Mesh object"); + else uiDefBut(block, BUT, B_DELEDGES, "Delete", 80,70,84,19, 0, 0, 0, 0, 0, "Deletes edges data from active Mesh"); if(me->mcol) val= 1.0; else val= 0.0; uiDefBut(block, LABEL, 0, "VertCol", 10,50,70,20, 0, val, 0, 0, 0, ""); if(me->mcol==NULL) { - uiDefBut(block, BUT, B_MAKEVERTCOL, "Make", 80,50,84,19, 0, 0, 0, 0, 0, "Enables vertex colour painting on active object"); + uiDefBut(block, BUT, B_MAKEVERTCOL, "Make", 80,50,84,19, 0, 0, 0, 0, 0, "Enables vertex colour painting on active Mesh"); } - else uiDefBut(block, BUT, B_DELVERTCOL, "Delete", 80,50,84,19, 0, 0, 0, 0, 0, "Deletes vertex colours on active object"); + else uiDefBut(block, BUT, B_DELVERTCOL, "Delete", 80,50,84,19, 0, 0, 0, 0, 0, "Deletes vertex colours on active Mesh"); if(me->tface) val= 1.0; else val= 0.0; uiDefBut(block, LABEL, 0, "TexFace", 10,30,70,20, 0, val, 0, 0, 0, ""); if(me->tface==NULL) { - uiDefBut(block, BUT, B_MAKE_TFACES, "Make", 80,30,84,19, 0, 0, 0, 0, 0, "Enables the active object's faces for UV coordinate mapping"); + uiDefBut(block, BUT, B_MAKE_TFACES, "Make", 80,30,84,19, 0, 0, 0, 0, 0, "Enables the active Mesh's faces for UV coordinate mapping"); } - else uiDefBut(block, BUT, B_DEL_TFACES, "Delete", 80,30,84,19, 0, 0, 0, 0, 0, "Deletes UV coordinates for active object's faces"); + else uiDefBut(block, BUT, B_DEL_TFACES, "Delete", 80,30,84,19, 0, 0, 0, 0, 0, "Deletes UV coordinates for active Mesh's faces"); if(me->msticky) val= 1.0; else val= 0.0; uiDefBut(block, LABEL, 0, "Sticky", 10,10,70,20, 0, val, 0, 0, 0, ""); if(me->msticky==NULL) { - uiDefBut(block, BUT, B_MAKESTICKY, "Make", 80,10,84,19, 0, 0, 0, 0, 0, "Creates Sticky coordinates for the active object from the current camera view background picture"); + uiDefBut(block, BUT, B_MAKESTICKY, "Make", 80,10,84,19, 0, 0, 0, 0, 0, "Creates Sticky coordinates for the active Mesh from the current camera view background picture"); } else uiDefBut(block, BUT, B_DELSTICKY, "Delete", 80,10,84,19, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates"); @@ -2217,9 +2217,10 @@ static void editing_panel_armature_type(Object *ob, bArmature *arm) uiButSetFunc(but, armature_recalc_func, ob, NULL); uiDefButBitI(block, TOG, ARM_DELAYDEFORM, REDRAWVIEW3D, "Delay Deform", 160, 180,150,20, &arm->flag, 0, 0, 0, 0, "Don't deform children when manipulating bones in pose mode"); uiBlockBeginAlign(block); - uiDefButI(block, ROW, REDRAWVIEW3D, "Octahedron", 10, 140,100,20, &arm->drawtype, 0, ARM_OCTA, 0, 0, "Draw bone as octahedra"); - uiDefButI(block, ROW, REDRAWVIEW3D, "Sticks", 110, 140,100,20, &arm->drawtype, 0, ARM_LINE, 0, 0, "Draw bone as simple 2d lines with dots"); - uiDefButI(block, ROW, REDRAWVIEW3D, "B-Bones", 210, 140,100,20, &arm->drawtype, 0, ARM_B_BONE, 0, 0, "Draw bone as boxes, showing subdivision and b-splines"); + uiDefButI(block, ROW, REDRAWVIEW3D, "Octahedron", 10, 140,75,20, &arm->drawtype, 0, ARM_OCTA, 0, 0, "Draw bones as octahedra"); + uiDefButI(block, ROW, REDRAWVIEW3D, "Stick", 85, 140,70,20, &arm->drawtype, 0, ARM_LINE, 0, 0, "Draw bones as simple 2d lines with dots"); + uiDefButI(block, ROW, REDRAWVIEW3D, "B-Bone", 155, 140,70,20, &arm->drawtype, 0, ARM_B_BONE, 0, 0, "Draw bones as boxes, showing subdivision and b-splines"); + uiDefButI(block, ROW, REDRAWVIEW3D, "Envelope", 225, 140,85,20, &arm->drawtype, 0, ARM_ENVELOPE, 0, 0, "Draw bones as extruded spheres, showing deformation influence volume"); uiBlockBeginAlign(block); uiDefButBitI(block, TOG, ARM_DRAWAXES, REDRAWVIEW3D, "Draw Axes", 10, 110,100,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes"); @@ -2286,7 +2287,7 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm) uiDefButBitI(block, TOG, BONE_HINGE, REDRAWVIEW3D, "Hinge", bx-10,by-38,117,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone"); uiDefButBitS(block, TOGN, 1,REDRAWVIEW3D, "Skinnable", bx+110, by-38, 105, 18, &curBone->boneclass, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone is included in automatic creation of vertex groups"); /* Hide in posemode flag */ - uiDefButBitI(block, TOG, BONE_HIDDEN, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode"); + uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode"); uiBlockEndAlign(block); by-=60; @@ -2346,7 +2347,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm) uiButSetFunc(but, armature_recalc_func, ob, NULL); uiDefButBitS(block, TOGN, 1,REDRAWVIEW3D, "Skinnable", bx+110, by-38, 105, 18, &curBone->boneclass, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone is included in automatic creation of vertex groups"); /* Hide in posemode flag */ - uiDefButBitI(block, TOG, BONE_HIDDEN, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode"); + uiDefButBitI(block, TOG, BONE_HIDDEN_P, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode"); uiBlockEndAlign(block); by-=60; diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index aa2a01d37c3..55cd70c6959 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -372,6 +372,388 @@ static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id) } +/* 16 values of sin function (still same result!) */ +static float si[16] = { + 0.00000000, + 0.20129852, 0.39435585, + 0.57126821, 0.72479278, + 0.84864425, 0.93775213, + 0.98846832, 0.99871650, + 0.96807711, 0.89780453, + 0.79077573, 0.65137248, + 0.48530196, 0.29936312, + 0.10116832 +}; +/* 16 values of cos function (still same result!) */ +static float co[16] ={ + 1.00000000, + 0.97952994, 0.91895781, + 0.82076344, 0.68896691, + 0.52896401, 0.34730525, + 0.15142777, -0.05064916, + -0.25065253, -0.44039415, + -0.61210598, -0.75875812, + -0.87434661, -0.95413925, + -0.99486932 +}; + + + +/* smat, imat = mat & imat to draw screenaligned */ +static void draw_sphere_bone_dist(float smat[][4], float imat[][4], int boneflag, bPoseChannel *pchan, EditBone *ebone) +{ + float head, tail, length, dist; + float *headvec, *tailvec, dirvec[3]; + + /* figure out the sizes of spheres */ + if(ebone) { + /* this routine doesn't call set_matrix_editbone() that calculates it */ + ebone->length = VecLenf(ebone->head, ebone->tail); + + length= ebone->length; + tail= ebone->rad_tail; + dist= ebone->dist; + if (ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) + head= ebone->parent->rad_tail; + else + head= ebone->rad_head; + headvec= ebone->head; + tailvec= ebone->tail; + } + else { + length= pchan->bone->length; + tail= pchan->bone->rad_tail; + dist= pchan->bone->dist; + if (pchan->parent && (pchan->bone->flag & BONE_IK_TOPARENT)) + head= pchan->parent->bone->rad_tail; + else + head= pchan->bone->rad_head; + headvec= pchan->pose_head; + tailvec= pchan->pose_tail; + } + + /* ***** draw it ***** */ + + /* move vector to viewspace */ + VecSubf(dirvec, tailvec, headvec); + Mat4Mul3Vecfl(smat, dirvec); + /* clear zcomp */ + dirvec[2]= 0.0; + /* move vector back */ + Mat4Mul3Vecfl(imat, dirvec); + + if(0.0f != Normalise(dirvec)) { + float norvec[3], vec1[3], vec2[3], vec[3]; + int a; + + //VecMulf(dirvec, head); + Crossf(norvec, dirvec, imat[2]); + + glBegin(GL_QUAD_STRIP); + + for(a=0; a<16; a++) { + vec[0]= - *(si+a) * dirvec[0] + *(co+a) * norvec[0]; + vec[1]= - *(si+a) * dirvec[1] + *(co+a) * norvec[1]; + vec[2]= - *(si+a) * dirvec[2] + *(co+a) * norvec[2]; + + vec1[0]= headvec[0] + head*vec[0]; + vec1[1]= headvec[1] + head*vec[1]; + vec1[2]= headvec[2] + head*vec[2]; + vec2[0]= headvec[0] + (head+dist)*vec[0]; + vec2[1]= headvec[1] + (head+dist)*vec[1]; + vec2[2]= headvec[2] + (head+dist)*vec[2]; + + glColor4ub(255, 255, 255, 50); + glVertex3fv(vec1); + //glColor4ub(255, 255, 255, 0); + glVertex3fv(vec2); + } + + for(a=15; a>=0; a--) { + vec[0]= *(si+a) * dirvec[0] + *(co+a) * norvec[0]; + vec[1]= *(si+a) * dirvec[1] + *(co+a) * norvec[1]; + vec[2]= *(si+a) * dirvec[2] + *(co+a) * norvec[2]; + + vec1[0]= tailvec[0] + tail*vec[0]; + vec1[1]= tailvec[1] + tail*vec[1]; + vec1[2]= tailvec[2] + tail*vec[2]; + vec2[0]= tailvec[0] + (tail+dist)*vec[0]; + vec2[1]= tailvec[1] + (tail+dist)*vec[1]; + vec2[2]= tailvec[2] + (tail+dist)*vec[2]; + + //glColor4ub(255, 255, 255, 50); + glVertex3fv(vec1); + //glColor4ub(255, 255, 255, 0); + glVertex3fv(vec2); + } + /* make it cyclic... */ + + vec[0]= - *(si) * dirvec[0] + *(co) * norvec[0]; + vec[1]= - *(si) * dirvec[1] + *(co) * norvec[1]; + vec[2]= - *(si) * dirvec[2] + *(co) * norvec[2]; + + vec1[0]= headvec[0] + head*vec[0]; + vec1[1]= headvec[1] + head*vec[1]; + vec1[2]= headvec[2] + head*vec[2]; + vec2[0]= headvec[0] + (head+dist)*vec[0]; + vec2[1]= headvec[1] + (head+dist)*vec[1]; + vec2[2]= headvec[2] + (head+dist)*vec[2]; + + //glColor4ub(255, 255, 255, 50); + glVertex3fv(vec1); + //glColor4ub(255, 255, 255, 0); + glVertex3fv(vec2); + + glEnd(); + } +} + + +/* smat, imat = mat & imat to draw screenaligned */ +static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) +{ + float head, tail, length; + float *headvec, *tailvec, dirvec[3]; + + /* figure out the sizes of spheres */ + if(ebone) { + /* this routine doesn't call set_matrix_editbone() that calculates it */ + ebone->length = VecLenf(ebone->head, ebone->tail); + + length= ebone->length; + tail= ebone->rad_tail; + if (ebone->parent && (boneflag & BONE_IK_TOPARENT)) + head= ebone->parent->rad_tail; + else + head= ebone->rad_head; + headvec= ebone->head; + tailvec= ebone->tail; + } + else { + length= pchan->bone->length; + tail= pchan->bone->rad_tail; + if (pchan->parent && (boneflag & BONE_IK_TOPARENT)) + head= pchan->parent->bone->rad_tail; + else + head= pchan->bone->rad_head; + headvec= pchan->pose_head; + tailvec= pchan->pose_tail; + } + + /* sphere root color */ + if(armflag & ARM_EDITMODE) { + if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT); + else BIF_ThemeColor(TH_VERTEX); + } + else if(armflag & ARM_POSEMODE) { + /* in black or selection color */ + if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40); + else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE); + else BIF_ThemeColor(TH_WIRE); + } + + /* Draw root point if we have no IK parent */ + if (!(boneflag & BONE_IK_TOPARENT)){ + if (id != -1) + glLoadName (id | BONESEL_ROOT); + + drawcircball(GL_LINE_LOOP, headvec, head, imat); + } + + /* Draw tip point */ + if(armflag & ARM_EDITMODE) { + if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT); + else BIF_ThemeColor(TH_VERTEX); + } + + if (id != -1) + glLoadName (id | BONESEL_TIP); + + drawcircball(GL_LINE_LOOP, tailvec, tail, imat); + + /* base */ + if(armflag & ARM_EDITMODE) { + if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_SELECT); + else BIF_ThemeColor(TH_WIRE); + } + + VecSubf(dirvec, tailvec, headvec); + + /* move vector to viewspace */ + Mat4Mul3Vecfl(smat, dirvec); + /* clear zcomp */ + dirvec[2]= 0.0; + /* move vector back */ + Mat4Mul3Vecfl(imat, dirvec); + + if(0.0f != Normalise(dirvec)) { + float norvech[3], norvect[3], vec[3]; + + VECCOPY(vec, dirvec); + + VecMulf(dirvec, head); + Crossf(norvech, dirvec, imat[2]); + + VecMulf(vec, tail); + Crossf(norvect, vec, imat[2]); + + if (id != -1) + glLoadName (id | BONESEL_BONE); + + glBegin(GL_LINES); + vec[0]= headvec[0] + norvech[0]; + vec[1]= headvec[1] + norvech[1]; + vec[2]= headvec[2] + norvech[2]; + glVertex3fv(vec); + vec[0]= tailvec[0] + norvect[0]; + vec[1]= tailvec[1] + norvect[1]; + vec[2]= tailvec[2] + norvect[2]; + glVertex3fv(vec); + vec[0]= headvec[0] - norvech[0]; + vec[1]= headvec[1] - norvech[1]; + vec[2]= headvec[2] - norvech[2]; + glVertex3fv(vec); + vec[0]= tailvec[0] - norvect[0]; + vec[1]= tailvec[1] - norvect[1]; + vec[2]= tailvec[2] - norvect[2]; + glVertex3fv(vec); + + glEnd(); + } +} + +/* does wire only for outline selecting */ +static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) +{ + GLUquadricObj *qobj; + float head, tail, length; + float fac1, fac2; + + glPushMatrix(); + qobj = gluNewQuadric(); + + /* figure out the sizes of spheres */ + if(ebone) { + length= ebone->length; + tail= ebone->rad_tail; + if (ebone->parent && (boneflag & BONE_IK_TOPARENT)) + head= ebone->parent->rad_tail; + else + head= ebone->rad_head; + } + else { + length= pchan->bone->length; + tail= pchan->bone->rad_tail; + if (pchan->parent && (boneflag & BONE_IK_TOPARENT)) + head= pchan->parent->bone->rad_tail; + else + head= pchan->bone->rad_head; + } + + /* move to z-axis space */ + glRotatef (-90.0f, 1.0f, 0.0f, 0.0f); + + if(dt==OB_SOLID) { + /* set up solid drawing */ + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_LIGHTING); + + gluQuadricDrawStyle(qobj, GLU_FILL); + glShadeModel(GL_SMOOTH); + } + else { + gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + } + + /* sphere root color */ + if(armflag & ARM_EDITMODE) { + if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT); + else BIF_ThemeColorShade(TH_BONE_SOLID, -30); + } + else if(armflag & ARM_POSEMODE) { + if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 10); + else if (boneflag & BONE_SELECTED) BIF_ThemeColorShade(TH_BONE_POSE, -30); + else BIF_ThemeColorShade(TH_BONE_SOLID, -30); + + } + else if(dt==OB_SOLID) + BIF_ThemeColorShade(TH_BONE_SOLID, -30); + + /* Draw root point if we have no IK parent */ + if (!(boneflag & BONE_IK_TOPARENT)){ + if (id != -1) + glLoadName (id | BONESEL_ROOT); + gluSphere( qobj, head, 16, 10); + } + + /* Draw tip point */ + if(armflag & ARM_EDITMODE) { + if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT); + else BIF_ThemeColorShade(TH_BONE_SOLID, -30); + } + + if (id != -1) + glLoadName (id | BONESEL_TIP); + + glTranslatef(0.0, 0.0, length); + gluSphere( qobj, tail, 16, 10); + glTranslatef(0.0, 0.0, -length); + + /* base */ + if(armflag & ARM_EDITMODE) { + if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_SELECT); + else BIF_ThemeColor(TH_BONE_SOLID); + } + else if(armflag & ARM_POSEMODE) { + if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40); + else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE); + else BIF_ThemeColor(TH_BONE_SOLID); + + } + else if(dt==OB_SOLID) + BIF_ThemeColor(TH_BONE_SOLID); + + fac1= (length-head)/length; + fac2= (length-tail)/length; + + if(length > head+tail) { + if (id != -1) + glLoadName (id | BONESEL_BONE); + + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0, -1.0); + + glTranslatef(0.0f, 0.0f, head); + gluCylinder(qobj, fac1*head + (1.0f-fac1)*tail, fac2*tail + (1.0f-fac2)*head, length-head-tail, 16, 1); + glTranslatef(0.0f, 0.0f, -head); + + glDisable(GL_POLYGON_OFFSET_FILL); + + /* draw sphere on extrema */ + glTranslatef(0.0f, 0.0f, length-tail); + gluSphere( qobj, fac2*tail + (1.0f-fac2)*head, 16, 10); + glTranslatef(0.0f, 0.0f, -length+tail); + + glTranslatef(0.0f, 0.0f, head); + gluSphere( qobj, fac1*head + (1.0f-fac1)*tail, 16, 10); + } + else { + /* 1 sphere in center */ + glTranslatef(0.0f, 0.0f, (head + length-tail)/2.0); + gluSphere( qobj, fac1*head + (1.0f-fac1)*tail, 16, 10); + } + + /* restore */ + if(dt==OB_SOLID) { + glShadeModel(GL_FLAT); + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + } + + glPopMatrix(); + gluDeleteQuadric(qobj); +} + static char bm_dot6[]= {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0}; static char bm_dot8[]= {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C}; @@ -606,12 +988,14 @@ static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsign } } -static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id) +static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, float length) { /* Draw a 3d octahedral bone, we use normalized space based on length, for glDisplayLists */ + glScalef(length, length, length); + /* set up solid drawing */ if(dt > OB_WIRE) { glEnable(GL_COLOR_MATERIAL); @@ -688,40 +1072,69 @@ static void draw_pose_channels(Base *base, int dt) bPoseChannel *pchan; Bone *bone; GLfloat tmp; + float smat[4][4], imat[4][4]; int index= -1; int do_dashed= 1; short flag, constflag; - /* little speedup, also make sure transparent only draws once */ - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); - /* hacky... prevent outline select from drawing dashed helplines */ glGetFloatv(GL_LINE_WIDTH, &tmp); if(tmp > 1.1) do_dashed= 0; + + /* precalc inverse matrix for drawing screen aligned */ + if(arm->drawtype==ARM_ENVELOPE) { + /* precalc inverse matrix for drawing screen aligned */ + mygetmatrix(smat); + Mat4MulFloat3(smat[0], 1.0f/VecLength(ob->obmat[0])); + Mat4Invert(imat, smat); + /* and draw blended distances */ + if(arm->flag & ARM_POSEMODE) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + //glShadeModel(GL_SMOOTH); + + if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); + + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + bone= pchan->bone; + if(bone && !(bone->flag & BONE_HIDDEN_P)) { + if(bone->flag & (BONE_SELECTED)) + draw_sphere_bone_dist(smat, imat, bone->flag, pchan, NULL); + } + } + + if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + //glShadeModel(GL_FLAT); + } + } + + /* little speedup, also make sure transparent only draws once */ + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); + /* if solid we draw that first, with selection codes, but without names, axes etc */ if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) { if(arm->flag & ARM_POSEMODE) index= base->selcol; for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { bone= pchan->bone; - if(bone && !(bone->flag & BONE_HIDDEN)) { + if(bone && !(bone->flag & BONE_HIDDEN_P)) { glPushMatrix(); glMultMatrixf(pchan->pose_mat); /* catch exception for bone with hidden parent */ flag= bone->flag; - if(bone->parent && (bone->parent->flag & BONE_HIDDEN)) + if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P)) flag &= ~BONE_IK_TOPARENT; - if(arm->drawtype==ARM_B_BONE) + if(arm->drawtype==ARM_ENVELOPE) + draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL); + else if(arm->drawtype==ARM_B_BONE) draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL); else { - /* scale the matrix to unit bone space */ - glScalef(bone->length, bone->length, bone->length); - - draw_bone(OB_SOLID, arm->flag, flag, 0, index); + draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->length); } glPopMatrix(); } @@ -747,7 +1160,7 @@ static void draw_pose_channels(Base *base, int dt) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { bone= pchan->bone; - if(bone && !(bone->flag & BONE_HIDDEN)) { + if(bone && !(bone->flag & BONE_HIDDEN_P)) { // Draw a line from our root to the parent's tip if (do_dashed && bone->parent && !(bone->flag & BONE_IK_TOPARENT) ){ @@ -763,12 +1176,14 @@ static void draw_pose_channels(Base *base, int dt) setlinestyle(0); } - glPushMatrix(); - glMultMatrixf(pchan->pose_mat); + if(arm->drawtype!=ARM_ENVELOPE) { + glPushMatrix(); + glMultMatrixf(pchan->pose_mat); + } /* catch exception for bone with hidden parent */ flag= bone->flag; - if(bone->parent && (bone->parent->flag & BONE_HIDDEN)) + if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P)) flag &= ~BONE_IK_TOPARENT; /* extra draw service for pose mode */ @@ -776,18 +1191,20 @@ static void draw_pose_channels(Base *base, int dt) if(pchan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) constflag |= PCHAN_HAS_ACTION; - if(arm->drawtype==ARM_LINE) + if(arm->drawtype==ARM_ENVELOPE) { + if(dt<OB_SOLID) + draw_sphere_bone_wire(smat, imat, arm->flag, flag, constflag, index, pchan, NULL); + } + else if(arm->drawtype==ARM_LINE) draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL); else if(arm->drawtype==ARM_B_BONE) draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL); else { - /* scale the matrix to unit bone space */ - glScalef(bone->length, bone->length, bone->length); - - draw_bone(OB_WIRE, arm->flag, flag, constflag, index); + draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length); } - glPopMatrix(); + if(arm->drawtype!=ARM_ENVELOPE) + glPopMatrix(); } if (index!= -1) index+= 0x10000; // pose bones count in higher 2 bytes only } @@ -864,24 +1281,58 @@ static void draw_ebones(Object *ob, int dt) { EditBone *eBone; bArmature *arm= ob->data; + float smat[4][4], imat[4][4]; unsigned int index; + int flag; + + /* envelope (deform distance) */ + if(arm->drawtype==ARM_ENVELOPE) { + /* precalc inverse matrix for drawing screen aligned */ + mygetmatrix(smat); + Mat4MulFloat3(smat[0], 1.0f/VecLength(ob->obmat[0])); + Mat4Invert(imat, smat); + + /* and draw blended distances */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + //glShadeModel(GL_SMOOTH); + + if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); + + for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){ + if(!(eBone->flag & BONE_HIDDEN_A)) + if(eBone->flag & (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL)) + draw_sphere_bone_dist(smat, imat, eBone->flag, NULL, eBone); + } + + if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + //glShadeModel(GL_FLAT); + } /* if solid we draw it first */ if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) { index= 0; for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){ - glPushMatrix(); - set_matrix_editbone(eBone); - - if(arm->drawtype==ARM_B_BONE) - draw_b_bone(OB_SOLID, arm->flag, eBone->flag, 0, index, NULL, eBone); - else { - /* scale the matrix to unit bone space */ - glScalef(eBone->length, eBone->length, eBone->length); - draw_bone(OB_SOLID, arm->flag, eBone->flag, 0, index); + if(!(eBone->flag & BONE_HIDDEN_A)) { + glPushMatrix(); + set_matrix_editbone(eBone); + + /* catch exception for bone with hidden parent */ + flag= eBone->flag; + if(eBone->parent && (eBone->parent->flag & BONE_HIDDEN_A)) + flag &= ~BONE_IK_TOPARENT; + + if(arm->drawtype==ARM_ENVELOPE) + draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone); + else if(arm->drawtype==ARM_B_BONE) + draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone); + else { + draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length); + } + + glPopMatrix(); } - - glPopMatrix(); } } @@ -897,36 +1348,47 @@ static void draw_ebones(Object *ob, int dt) index= 0; // do selection codes for (eBone=G.edbo.first; eBone; eBone=eBone->next){ - - glPushMatrix(); - set_matrix_editbone(eBone); - - if(arm->drawtype==ARM_LINE) - draw_line_bone(arm->flag, eBone->flag, 0, index, NULL, eBone); - else if(arm->drawtype==ARM_B_BONE) - draw_b_bone(OB_WIRE, arm->flag, eBone->flag, 0, index, NULL, eBone); - else { - /* scale the matrix to unit bone space */ - glScalef(eBone->length, eBone->length, eBone->length); - draw_bone(OB_WIRE, arm->flag, eBone->flag, 0, index); - } - if(arm->flag & ARM_DRAWAXES) - drawaxes(0.25f); - - glPopMatrix(); - - /* offset to parent */ - if (eBone->parent) { - BIF_ThemeColor(TH_WIRE); - glLoadName (-1); // -1 here is OK! - setlinestyle(3); + if(!(eBone->flag & BONE_HIDDEN_A)) { - glBegin(GL_LINES); - glVertex3fv(eBone->parent->tail); - glVertex3fv(eBone->head); - glEnd(); + /* catch exception for bone with hidden parent */ + flag= eBone->flag; + if(eBone->parent && (eBone->parent->flag & BONE_HIDDEN_A)) + flag &= ~BONE_IK_TOPARENT; - setlinestyle(0); + if(arm->drawtype==ARM_ENVELOPE) { + if(dt<OB_SOLID) + draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone); + } + else { + glPushMatrix(); + set_matrix_editbone(eBone); + + if(arm->drawtype==ARM_LINE) + draw_line_bone(arm->flag, flag, 0, index, NULL, eBone); + else if(arm->drawtype==ARM_B_BONE) + draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone); + else + draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length); + + if(arm->flag & ARM_DRAWAXES) + drawaxes(0.25f); + + glPopMatrix(); + } + + /* offset to parent */ + if (eBone->parent) { + BIF_ThemeColor(TH_WIRE); + glLoadName (-1); // -1 here is OK! + setlinestyle(3); + + glBegin(GL_LINES); + glVertex3fv(eBone->parent->tail); + glVertex3fv(eBone->head); + glEnd(); + + setlinestyle(0); + } } if(index!=-1) index++; } @@ -944,20 +1406,21 @@ static void draw_ebones(Object *ob, int dt) if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){ - - if(eBone->flag & BONE_SELECTED) BIF_ThemeColor(TH_TEXT_HI); - else BIF_ThemeColor(TH_TEXT); - - VecMidf(vec, eBone->head, eBone->tail); - glRasterPos3fv(vec); - BMF_DrawString(G.font, " "); - BMF_DrawString(G.font, eBone->name); + if(!(eBone->flag & BONE_HIDDEN_A)) { + + if(eBone->flag & BONE_SELECTED) BIF_ThemeColor(TH_TEXT_HI); + else BIF_ThemeColor(TH_TEXT); + + VecMidf(vec, eBone->head, eBone->tail); + glRasterPos3fv(vec); + BMF_DrawString(G.font, " "); + BMF_DrawString(G.font, eBone->name); + } } if(G.vd->zbuf) glEnable(GL_DEPTH_TEST); } } - } /* called from drawobject.c */ @@ -966,9 +1429,16 @@ void draw_armature(Base *base, int dt) Object *ob= base->object; bArmature *arm= ob->data; - /* we use color for solid lighting */ - glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); - glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // only for lighting... + if(dt>OB_WIRE) { + /* we use color for solid lighting */ + glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); + glEnable(GL_COLOR_MATERIAL); + glColor3ub(0,0,0); // clear spec + glDisable(GL_COLOR_MATERIAL); + + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // only for lighting... + } /* arm->flag is being used to detect mode... */ /* editmode? */ diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 9db631cc3f7..16b7a52937c 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -163,8 +163,10 @@ static void make_boneList(ListBase* list, ListBase *bones, EditBone *parent) eBone->zwidth= curBone->zwidth; eBone->ease1= curBone->ease1; eBone->ease2= curBone->ease2; + eBone->rad_head= curBone->rad_head; + eBone->rad_tail= curBone->rad_tail; eBone->segments = curBone->segments; - eBone->boneclass = curBone->boneclass; + eBone->boneclass = curBone->boneclass; BLI_addtail (list, eBone); @@ -256,6 +258,8 @@ static void editbones_to_armature (ListBase *list, Object *ob) newBone->zwidth = eBone->zwidth; newBone->ease1= eBone->ease1; newBone->ease2= eBone->ease2; + newBone->rad_head= eBone->rad_head; + newBone->rad_tail= eBone->rad_tail; newBone->segments= eBone->segments; newBone->boneclass = eBone->boneclass; @@ -1162,11 +1166,11 @@ static EditBone *add_editbone(void) { EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone"); - BLI_addtail(&G.edbo, bone); - strcpy (bone->name,"Bone"); unique_editbone_name (bone->name); + BLI_addtail(&G.edbo, bone); + bone->flag |= BONE_TIPSEL; bone->weight= 1.0F; bone->dist= 1.0F; @@ -1174,6 +1178,8 @@ static EditBone *add_editbone(void) bone->zwidth= 0.1; bone->ease1= 1.0; bone->ease2= 1.0; + bone->rad_head= 0.25; + bone->rad_tail= 0.1; bone->segments= 1; bone->boneclass = BONE_SKINNABLE; @@ -1381,6 +1387,55 @@ void adduplicate_armature(void) /* *************** END Adding stuff in editmode *************** */ /* *************** Tools in editmode *********** */ + +void hide_selected_armature_bones(void) +{ + EditBone *ebone; + + for (ebone = G.edbo.first; ebone; ebone=ebone->next){ + if(ebone->flag & (BONE_SELECTED)) { + ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); + ebone->flag |= BONE_HIDDEN_A; + } + } + countall(); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); +} + +void hide_unselected_armature_bones(void) +{ + EditBone *ebone; + + for (ebone = G.edbo.first; ebone; ebone=ebone->next){ + if(ebone->flag & (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL)); + else { + ebone->flag &= ~BONE_ACTIVE; + ebone->flag |= BONE_HIDDEN_A; + } + } + countall(); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); +} + +void show_all_armature_bones(void) +{ + EditBone *ebone; + + for (ebone = G.edbo.first; ebone; ebone=ebone->next){ + if(ebone->flag & BONE_HIDDEN_A) { + ebone->flag |= (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL); + ebone->flag &= ~BONE_HIDDEN_A; + } + } + countall(); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); +} + + + /* the "IK" button in editbuttons */ void attach_bone_to_parent_cb(void *bonev, void *arg2_unused) { @@ -1558,13 +1613,34 @@ void extrude_armature(int forked) { bArmature *arm= G.obedit->data; EditBone *newbone, *ebone, *flipbone, *first=NULL, *partest; - int a, totbone= 0; + int a, totbone= 0, do_extrude; TEST_EDITARMATURE; + /* since we allow root extrude too, we have to make sure selection is OK */ + for (ebone = G.edbo.first; ebone; ebone=ebone->next){ + if(ebone->flag & BONE_ROOTSEL) { + if(ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) { + if(ebone->parent->flag & BONE_TIPSEL) + ebone->flag &= ~BONE_ROOTSEL; + } + } + } + /* Duplicate the necessary bones */ for (ebone = G.edbo.first; ((ebone) && (ebone!=first)); ebone=ebone->next){ - if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED)) { + + /* we extrude per definition the tip */ + do_extrude= 0; + if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED)) + do_extrude= 1; + else if(ebone->flag & BONE_ROOTSEL) { + /* but, a bone with parent deselected we do the root... */ + if(ebone->parent && (ebone->parent->flag & BONE_TIPSEL)); + else do_extrude= 2; + } + + if (do_extrude) { /* we re-use code for mirror editing... */ flipbone= NULL; @@ -1572,7 +1648,7 @@ void extrude_armature(int forked) flipbone= armature_bone_get_mirrored(ebone); if (flipbone) { forked= 0; // we extrude 2 different bones - if(flipbone->flag & (BONE_TIPSEL|BONE_SELECTED)) + if(flipbone->flag & (BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED)) /* don't want this bone to be selected... */ flipbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE); } @@ -1592,29 +1668,43 @@ void extrude_armature(int forked) totbone++; newbone = MEM_callocN(sizeof(EditBone), "extrudebone"); - VECCOPY (newbone->head, ebone->tail); - VECCOPY (newbone->tail, newbone->head); - newbone->parent = ebone; - - newbone->flag = ebone->flag & BONE_TIPSEL; // copies it, in case mirrored bone + if(do_extrude==1) { + VECCOPY (newbone->head, ebone->tail); + VECCOPY (newbone->tail, newbone->head); + newbone->parent = ebone; + + newbone->flag = ebone->flag & BONE_TIPSEL; // copies it, in case mirrored bone + } + else { + VECCOPY(newbone->head, ebone->head); + VECCOPY(newbone->tail, ebone->head); + newbone->parent= ebone->parent; + + newbone->flag= BONE_TIPSEL; + } + newbone->weight= ebone->weight; newbone->dist= ebone->dist; newbone->xwidth= ebone->xwidth; newbone->zwidth= ebone->zwidth; newbone->ease1= ebone->ease1; newbone->ease2= ebone->ease2; - newbone->segments= ebone->segments; + newbone->rad_head= ebone->rad_tail; // dont copy entire bone... + newbone->rad_tail= ebone->rad_tail; + newbone->segments= 1; newbone->boneclass= ebone->boneclass; /* See if there are any ik children of the parent */ - for (partest = G.edbo.first; partest; partest=partest->next){ - if ((partest->parent == ebone) && (partest->flag & BONE_IK_TOPARENT)) - break; + if(do_extrude==1) { + for (partest = G.edbo.first; partest; partest=partest->next){ + if ((partest->parent == ebone) && (partest->flag & BONE_IK_TOPARENT)) + break; + } + + if (!partest) + newbone->flag |= BONE_IK_TOPARENT; } - if (!partest) - newbone->flag |= BONE_IK_TOPARENT; - strcpy (newbone->name, ebone->name); if(flipbone && forked) { // only set if mirror edit @@ -1771,7 +1861,7 @@ static void deselect_bonechildren (Object *ob, Bone *bone, int mode) if (mode==0) bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); else if (mode==1) { - if(!(bone->flag & BONE_HIDDEN)) + if(!(bone->flag & BONE_HIDDEN_P)) bone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); } else bone->flag &= ~BONE_ACTIVE; @@ -2000,12 +2090,15 @@ static void add_verts_to_closest_dgroup(Object *ob, Object *par) * on the subsurf limit surface is used to generate * the weights rather than the verts on the cage * mesh. + * + * ("Limit surface" = same amount of vertices as mesh, but vertices + * moved to the subsurfed position, like for 'optimal'). */ bArmature *arm; Bone **bonelist, **bonehandle, *bone; bDeformGroup **dgrouplist, **dgrouphandle, *defgroup; - float *distance, mindist = 0.0, weight = 0.0; + float *distance; float root[3]; float tip[3]; float real_co[3]; @@ -2043,7 +2136,7 @@ static void add_verts_to_closest_dgroup(Object *ob, Object *par) dgroup_skinnable); /* create an array of floats that will be used for each vert - * to hold the distance to each bone. + * to hold the distance-factor to each bone. */ distance = MEM_mallocN(numbones*sizeof(float), "distance"); @@ -2087,21 +2180,10 @@ static void add_verts_to_closest_dgroup(Object *ob, Object *par) VECCOPY(tip, bone->arm_tail); Mat4MulVecfl(par->obmat, tip); - /* store the distance from the bone to - * the vert - */ - distance[j] = dist_to_bone(real_co, root, tip); - - /* if this is the first bone, or if this - * bone is less than mindist, then set this - * distance to mindist + /* store the distance-factor from the vertex to + * the bone */ - if (j == 0) { - mindist = distance[j]; - } - else if (distance[j] < mindist) { - mindist = distance[j]; - } + distance[j]= distfactor_to_bone (real_co, root, tip, bone->rad_head, bone->rad_tail, bone->dist); } /* for each deform group ... @@ -2109,31 +2191,12 @@ static void add_verts_to_closest_dgroup(Object *ob, Object *par) for (j=0; j < numbones; ++j) { defgroup = dgrouplist[j]; - /* if the cooresponding bone is the closest one - * add the vert to the deform group with weight 1 + /* add the vert to the deform group if weight!=0.0 */ - if (distance[j] <= mindist) { - add_vert_to_defgroup (ob, defgroup, i, 1.0, WEIGHT_REPLACE); - } - - /* if the cooresponding bone is within 10% of the - * nearest distance, add the vert to the - * deform group with a weight that declines with - * distance - */ - else if (distance[j] <= mindist*1.10) { - if (mindist > 0) - weight = 1.0 - (distance[j] - mindist) / (mindist * 0.10); - add_vert_to_defgroup (ob, defgroup, i, weight, WEIGHT_REPLACE); - } - - /* if the cooresponding bone is outside of the 10% tolerance - * then remove the vert from the weight group (if it is - * in that group) - */ - else { + if (distance[j]!=0.0) + add_vert_to_defgroup (ob, defgroup, i, distance[j], WEIGHT_REPLACE); + else remove_vert_defgroup (ob, defgroup, i); - } } } @@ -2191,7 +2254,7 @@ void create_vgroups_from_armature(Object *ob, Object *par) static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr) { if (bone->flag & BONE_SELECTED) { - bone->flag |= BONE_HIDDEN; + bone->flag |= BONE_HIDDEN_P; bone->flag &= ~BONE_SELECTED; } return 0; @@ -2211,12 +2274,13 @@ void hide_selected_pose_bones(void) hide_selected_pose_bone); allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); } static int hide_unselected_pose_bone(Object *ob, Bone *bone, void *ptr) { if (~bone->flag & BONE_SELECTED) { - bone->flag |= BONE_HIDDEN; + bone->flag |= BONE_HIDDEN_P; } return 0; } @@ -2235,12 +2299,13 @@ void hide_unselected_pose_bones(void) hide_unselected_pose_bone); allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); } static int show_pose_bone(Object *ob, Bone *bone, void *ptr) { - if (bone->flag & BONE_HIDDEN) { - bone->flag &= ~BONE_HIDDEN; + if (bone->flag & BONE_HIDDEN_P) { + bone->flag &= ~BONE_HIDDEN_P; bone->flag |= BONE_SELECTED; } @@ -2261,6 +2326,7 @@ void show_all_pose_bones(void) show_pose_bone); allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); } @@ -2317,86 +2383,90 @@ void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep) char newname[MAXBONENAME]; char oldname[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(G.obedit && G.obedit->data==arm) { - EditBone *eBone; - - eBone= editbone_name_exists(oldname); - if(eBone) { - unique_editbone_name (newname); - BLI_strncpy(eBone->name, newname, 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(G.obedit && G.obedit->data==arm) { + EditBone *eBone; + + eBone= editbone_name_exists(oldname); + if(eBone) { + unique_editbone_name (newname); + BLI_strncpy(eBone->name, newname, MAXBONENAME); + } + else return; } - else return; - } - else { - Bone *bone= get_named_bone (arm, oldname); + else { + Bone *bone= get_named_bone (arm, oldname); - if(bone) { - unique_bone_name (arm, newname); - BLI_strncpy(bone->name, newname, MAXBONENAME); - } - else return; - } - - /* do entire dbase */ - for(ob= G.main->object.first; ob; ob= ob->id.next) { - /* we have the object using the armature */ - if(arm==ob->data) { - Object *cob; - bAction *act; - bActionChannel *chan; - - /* Rename action channel if necessary */ - act = ob->action; - if (act && !act->id.lib){ - /* Find the appropriate channel */ - chan= get_named_actionchannel(act, oldname); - if(chan) BLI_strncpy(chan->name, newname, MAXBONENAME); + if(bone) { + unique_bone_name (arm, newname); + BLI_strncpy(bone->name, newname, MAXBONENAME); } - - /* Rename the pose channel, if it exists */ - if (ob->pose) { - bPoseChannel *pchan = get_pose_channel(ob->pose, oldname); - if (pchan) { - BLI_strncpy (pchan->name, newname, MAXBONENAME); + else return; + } + + /* do entire dbase */ + for(ob= G.main->object.first; ob; ob= ob->id.next) { + /* we have the object using the armature */ + if(arm==ob->data) { + Object *cob; + bAction *act; + bActionChannel *chan; + + /* Rename action channel if necessary */ + act = ob->action; + if (act && !act->id.lib){ + /* Find the appropriate channel */ + chan= get_named_actionchannel(act, oldname); + if(chan) BLI_strncpy(chan->name, newname, MAXBONENAME); } - } - - /* and actually do the NLA too */ - /* (todo) */ - - /* 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); + + /* Rename the pose channel, if it exists */ + if (ob->pose) { + bPoseChannel *pchan = get_pose_channel(ob->pose, oldname); + if (pchan) { + BLI_strncpy (pchan->name, newname, MAXBONENAME); + } + } + + /* and actually do the NLA too */ + /* (todo) */ + + /* 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); } - else if(ob->partype==PARSKEL) { - bDeformGroup *dg; - /* bone name in defgroup */ - for (dg=ob->defbase.first; dg; dg=dg->next) { - if(!strcmp(dg->name, oldname)) - BLI_strncpy(dg->name, newname, MAXBONENAME); + + /* 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); + } + else if(ob->partype==PARSKEL) { + bDeformGroup *dg; + /* bone name in defgroup */ + for (dg=ob->defbase.first; dg; dg=dg->next) { + if(!strcmp(dg->name, oldname)) + BLI_strncpy(dg->name, newname, MAXBONENAME); + } } } } diff --git a/source/blender/src/editdeform.c b/source/blender/src/editdeform.c index f600c8e5537..053151e5c4b 100644 --- a/source/blender/src/editdeform.c +++ b/source/blender/src/editdeform.c @@ -193,9 +193,16 @@ void del_defgroup (Object *ob) /* Update the active material index if necessary */ if (ob->actdef==BLI_countlist(&ob->defbase)) ob->actdef--; - + /* Remove the group */ BLI_freelinkN (&ob->defbase, defgroup); + + /* remove all dverts */ + if(ob->actdef==0) { + Mesh *me= ob->data; + free_dverts(me->dvert, me->totvert); + me->dvert= NULL; + } } void create_dverts(Mesh *me) @@ -288,8 +295,11 @@ void add_vert_defnr (Object *ob, int def_nr, int vertnum, /* get the vert */ - dv = ((Mesh*)ob->data)->dvert + vertnum; - + if(((Mesh*)ob->data)->dvert) + dv = ((Mesh*)ob->data)->dvert + vertnum; + else + return; + /* Lets first check to see if this vert is * already in the weight group -- if so * lets update it diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 04195d14cbf..aef790fa439 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -976,7 +976,9 @@ void load_editMesh(void) if(G.totface==0) mface= NULL; else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh face"); - if (G.totvert==0 || me->dvert==NULL) dvert= NULL; + /* are we adding dverts? */ + if (G.totvert==0) dvert= NULL; + else if(G.obedit->defbase.first==NULL) dvert= NULL; else dvert = MEM_callocN(G.totvert*sizeof(MDeformVert), "loadeditMesh3"); if (me->dvert) free_dverts(me->dvert, me->totvert); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index eea9130ae04..f9ea1bd687e 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -1953,6 +1953,13 @@ void special_editmenu(void) BIF_undo_push("Shared VertexCol"); } } + else if(G.f & G_WEIGHTPAINT) { + if(ob->parent && (ob->parent->flag & OB_POSEMODE)) { + nr= pupmenu("Specials%t|Apply Bone Envelopes to VertexGroups %x1"); + if(nr==1) + pose_adds_vgroups(ob); + } + } else { Base *base, *base_select= NULL; diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 6f2d48b0ef0..fa26a05f386 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -3644,7 +3644,6 @@ static char *view3d_modeselect_pup(void) sprintf(tempstr, formatstr, "Texture Paint", V3D_TEXTUREPAINTMODE_SEL, ICON_TPAINT_HLT); strcat(string, tempstr); - if ( ((Mesh*)(ob->data))->dvert) { sprintf(tempstr, formatstr, "Weight Paint", V3D_WEIGHTPAINTMODE_SEL, ICON_WPAINT_HLT); strcat(string, tempstr); @@ -3704,6 +3703,7 @@ static char *propfalloff_pup(void) void do_view3d_buttons(short event) { + Object *ob= OBACT; int bit; /* watch it: if curarea->win does not exist, check that when calling direct drawing routines */ @@ -3778,7 +3778,6 @@ void do_view3d_buttons(short event) case B_MODESELECT: if (G.vd->modeselect == V3D_OBJECTMODE_SEL) { - Object *ob= OBACT; G.vd->flag &= ~V3D_MODE; G.f &= ~G_VERTEXPAINT; /* Switch off vertex paint */ @@ -3837,7 +3836,7 @@ void do_view3d_buttons(short event) } } else if (G.vd->modeselect == V3D_WEIGHTPAINTMODE_SEL) { - if (!(G.f & G_WEIGHTPAINT) && (OBACT && OBACT->type == OB_MESH) && ((((Mesh*)(OBACT->data))->dvert))) { + if (!(G.f & G_WEIGHTPAINT) && (ob && ob->type == OB_MESH) && ((((Mesh*)(ob->data))->dvert))) { G.vd->flag &= ~V3D_MODE; G.f &= ~G_VERTEXPAINT; /* Switch off vertex paint */ G.f &= ~G_TEXTUREPAINT; /* Switch off texture paint */ @@ -3847,7 +3846,6 @@ void do_view3d_buttons(short event) } } else if (G.vd->modeselect == V3D_POSEMODE_SEL) { - Object *ob= OBACT; if (ob && !(ob->flag & OB_POSEMODE)) { G.vd->flag &= ~V3D_MODE; @@ -3944,6 +3942,7 @@ void do_view3d_buttons(short event) static void view3d_header_pulldowns(uiBlock *block, short *xcoord) { + Object *ob= OBACT; short xmax, xco= *xcoord; /* pull down menus */ @@ -3966,27 +3965,26 @@ static void view3d_header_pulldowns(uiBlock *block, short *xcoord) xmax= GetButStringLength("Select"); if (G.obedit) { - if (OBACT && OBACT->type == OB_MESH) { + if (ob && ob->type == OB_MESH) { uiDefPulldownBut(block, view3d_select_meshmenu, NULL, "Select", xco,-2, xmax-3, 24, ""); - } else if (OBACT && (OBACT->type == OB_CURVE || OBACT->type == OB_SURF)) { + } else if (ob && (ob->type == OB_CURVE || ob->type == OB_SURF)) { uiDefPulldownBut(block, view3d_select_curvemenu, NULL, "Select", xco,-2, xmax-3, 24, ""); - } else if (OBACT && OBACT->type == OB_FONT) { + } else if (ob && ob->type == OB_FONT) { uiDefPulldownBut(block, view3d_select_meshmenu, NULL, "Select", xco, -2, xmax-3, 24, ""); - } else if (OBACT && OBACT->type == OB_MBALL) { + } else if (ob && ob->type == OB_MBALL) { uiDefPulldownBut(block, view3d_select_metaballmenu, NULL, "Select", xco,-2, xmax-3, 24, ""); - } else if (OBACT && OBACT->type == OB_LATTICE) { + } else if (ob && ob->type == OB_LATTICE) { uiDefPulldownBut(block, view3d_select_latticemenu, NULL, "Select", xco,-2, xmax-3, 24, ""); - } else if (OBACT && OBACT->type == OB_ARMATURE) { + } else if (ob && ob->type == OB_ARMATURE) { uiDefPulldownBut(block, view3d_select_armaturemenu, NULL, "Select", xco,-2, xmax-3, 24, ""); } } else if (G.f & G_FACESELECT) { - if (OBACT && OBACT->type == OB_MESH) { + if (ob && ob->type == OB_MESH) { uiDefPulldownBut(block, view3d_select_faceselmenu, NULL, "Select", xco,-2, xmax-3, 24, ""); } } else if ((G.f & G_VERTEXPAINT) || (G.f & G_TEXTUREPAINT) || (G.f & G_WEIGHTPAINT)) { uiDefBut(block, LABEL,0,"", xco, 0, xmax, 20, 0, 0, 0, 0, 0, ""); } else { - Object *ob= OBACT; if (ob && (ob->flag & OB_POSEMODE)) uiDefPulldownBut(block, view3d_select_pose_armaturemenu, NULL, "Select", xco,-2, xmax-3, 24, ""); @@ -3996,31 +3994,31 @@ static void view3d_header_pulldowns(uiBlock *block, short *xcoord) xco+= xmax; if (G.obedit) { - if (OBACT && OBACT->type == OB_MESH) { + if (ob && ob->type == OB_MESH) { xmax= GetButStringLength("Mesh"); uiDefPulldownBut(block, view3d_edit_meshmenu, NULL, "Mesh", xco,-2, xmax-3, 24, ""); xco+= xmax; - } else if (OBACT && OBACT->type == OB_CURVE) { + } else if (ob && ob->type == OB_CURVE) { xmax= GetButStringLength("Curve"); uiDefPulldownBut(block, view3d_edit_curvemenu, NULL, "Curve", xco,-2, xmax-3, 24, ""); xco+= xmax; - } else if (OBACT && OBACT->type == OB_SURF) { + } else if (ob && ob->type == OB_SURF) { xmax= GetButStringLength("Surface"); uiDefPulldownBut(block, view3d_edit_curvemenu, NULL, "Surface", xco,-2, xmax-3, 24, ""); xco+= xmax; - } else if (OBACT && OBACT->type == OB_FONT) { + } else if (ob && ob->type == OB_FONT) { xmax= GetButStringLength("Text"); uiDefPulldownBut(block, view3d_edit_textmenu, NULL, "Text", xco,-2, xmax-3, 24, ""); xco+= xmax; - } else if (OBACT && OBACT->type == OB_MBALL) { + } else if (ob && ob->type == OB_MBALL) { xmax= GetButStringLength("Metaball"); uiDefPulldownBut(block, view3d_edit_metaballmenu, NULL, "Metaball", xco,-2, xmax-3, 24, ""); xco+= xmax; - } else if (OBACT && OBACT->type == OB_LATTICE) { + } else if (ob && ob->type == OB_LATTICE) { xmax= GetButStringLength("Lattice"); uiDefPulldownBut(block, view3d_edit_latticemenu, NULL, "Lattice", xco,-2, xmax-3, 24, ""); xco+= xmax; - } else if (OBACT && OBACT->type == OB_ARMATURE) { + } else if (ob && ob->type == OB_ARMATURE) { xmax= GetButStringLength("Armature"); uiDefPulldownBut(block, view3d_edit_armaturemenu, NULL, "Armature", xco,-2, xmax-3, 24, ""); xco+= xmax; @@ -4032,14 +4030,12 @@ static void view3d_header_pulldowns(uiBlock *block, short *xcoord) xco+= xmax; } else if (G.f & G_FACESELECT) { - if (OBACT && OBACT->type == OB_MESH) { + if (ob && ob->type == OB_MESH) { xmax= GetButStringLength("Face"); uiDefPulldownBut(block, view3d_faceselmenu, NULL, "Face", xco,-2, xmax-3, 24, ""); xco+= xmax; } } else { - Object *ob= OBACT; - if (ob && (ob->flag & OB_POSEMODE)) { xmax= GetButStringLength("Pose"); uiDefPulldownBut(block, view3d_pose_armaturemenu, NULL, "Pose", xco,-2, xmax-3, 24, ""); diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index 66f02ed442b..af4218011de 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -1235,7 +1235,7 @@ static int tree_element_active_posechannel(TreeElement *te, TreeStoreElem *tsele bPoseChannel *pchan= te->directdata; if(set) { - if(!(pchan->bone->flag & BONE_HIDDEN)) { + if(!(pchan->bone->flag & BONE_HIDDEN_P)) { if(G.qual & LR_SHIFTKEY) deselectall_posearmature(ob, 2); // 2 = clear active tag else deselectall_posearmature(ob, 0); // 0 = deselect @@ -1260,7 +1260,7 @@ static int tree_element_active_bone(TreeElement *te, TreeStoreElem *tselem, int Bone *bone= te->directdata; if(set) { - if(!(bone->flag & BONE_HIDDEN)) { + if(!(bone->flag & BONE_HIDDEN_P)) { if(G.qual & LR_SHIFTKEY) deselectall_posearmature(OBACT, 2); // 2 is clear active tag else deselectall_posearmature(OBACT, 0); bone->flag |= BONE_SELECTED|BONE_ACTIVE; @@ -1287,16 +1287,19 @@ static int tree_element_active_ebone(TreeElement *te, TreeStoreElem *tselem, int EditBone *ebone= te->directdata; if(set) { - if(G.qual & LR_SHIFTKEY) deselectall_armature(2); // only clear active tag - else deselectall_armature(0); // deselect + if(!(ebone->flag & BONE_HIDDEN_A)) { + + if(G.qual & LR_SHIFTKEY) deselectall_armature(2); // only clear active tag + else deselectall_armature(0); // deselect - ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_ACTIVE; - // flush to parent? - if(ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) ebone->parent->flag |= BONE_TIPSEL; - - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWOOPS, 0); - allqueue(REDRAWACTION, 0); + ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_ACTIVE; + // flush to parent? + if(ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) ebone->parent->flag |= BONE_TIPSEL; + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWOOPS, 0); + allqueue(REDRAWACTION, 0); + } } else { if (ebone->flag & BONE_SELECTED) return 1; diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 75a10df9b6c..616089659f7 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -37,6 +37,8 @@ #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -45,6 +47,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" +#include "BKE_deform.h" #include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_global.h" @@ -54,6 +57,7 @@ #include "BIF_editarmature.h" #include "BIF_editaction.h" #include "BIF_editconstraint.h" +#include "BIF_editdeform.h" #include "BIF_gl.h" #include "BIF_graphics.h" #include "BIF_interface.h" @@ -527,6 +531,62 @@ void paste_posebuf (int flip) BIF_undo_push("Paste Action Pose"); } +/* ********************************************** */ + +void pose_adds_vgroups(Object *meshobj) +{ + Object *poseobj= meshobj->parent; + bPoseChannel *pchan; + Bone *bone; + bDeformGroup *dg; + Mesh *me= meshobj->data; + MVert *mvert; + float head[3], tail[3], vec[3], fac; + int i; + + if(poseobj==NULL || (poseobj->flag & OB_POSEMODE)==0) return; + + for(pchan= poseobj->pose->chanbase.first; pchan; pchan= pchan->next) { + bone= pchan->bone; + if(bone->flag & (BONE_SELECTED)) { + + /* check if mesh has vgroups */ + dg= get_named_vertexgroup(meshobj, bone->name); + if(dg==NULL) + dg= add_defgroup_name(meshobj, bone->name); + + /* get the root of the bone in global coords */ + VECCOPY(head, bone->arm_head); + Mat4MulVecfl(poseobj->obmat, head); + + /* get the tip of the bone in global coords */ + VECCOPY(tail, bone->arm_tail); + Mat4MulVecfl(poseobj->obmat, tail); + + /* todo; get the optimal vertices instead of mverts */ + mvert= me->mvert; + for ( i=0 ; i < me->totvert ; i++ , mvert++) { + VECCOPY(vec, mvert->co); + Mat4MulVecfl(meshobj->obmat, vec); + + /* get the distance-factor from the vertex to bone */ + fac= distfactor_to_bone (vec, head, tail, bone->rad_head, bone->rad_tail, bone->dist); + + /* add to vgroup. this call also makes me->dverts */ + if(fac!=0.0f) + add_vert_to_defgroup (meshobj, dg, i, fac, WEIGHT_REPLACE); + else + remove_vert_defgroup (meshobj, dg, i); + } + } + } + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + + DAG_object_flush_update(G.scene, meshobj, OB_RECALC_DATA); // and all its relations + +} /* ********************************************** */ diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 41b46933877..ce676cf87a2 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -54,6 +54,7 @@ #include "BLI_linklist.h" #include "DNA_action_types.h" +#include "DNA_armature_types.h" #include "DNA_curve_types.h" #include "DNA_image_types.h" #include "DNA_ipo_types.h" @@ -1306,6 +1307,14 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if((G.qual==0)) hide_mball(0); } + else if(G.obedit->type==OB_ARMATURE) { + if (G.qual==0) + hide_selected_armature_bones(); + else if (G.qual==LR_SHIFTKEY) + hide_unselected_armature_bones(); + else if (G.qual==LR_ALTKEY) + show_all_armature_bones(); + } } else if(G.f & G_FACESELECT) hide_tface(); @@ -1568,8 +1577,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.obedit) { if(G.qual==LR_ALTKEY) { - if(G.obedit->type==OB_ARMATURE) + if(G.obedit->type==OB_ARMATURE) { initTransform(TFM_BONESIZE, CTX_NONE); + } else initTransform(TFM_SHRINKFATTEN, CTX_NONE); Transform(); @@ -1581,7 +1591,15 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.qual==LR_SHIFTKEY) snapmenu(); else if(G.qual==0) { - initTransform(TFM_RESIZE, CTX_NONE); + if(G.obedit->type==OB_ARMATURE) { + bArmature *arm= G.obedit->data; + if(arm->drawtype==ARM_ENVELOPE) + initTransform(TFM_BONE_ENVELOPE, CTX_NONE); + else + initTransform(TFM_RESIZE, CTX_NONE); + } + else + initTransform(TFM_RESIZE, CTX_NONE); Transform(); } else if(G.qual==(LR_SHIFTKEY|LR_CTRLKEY)){ @@ -1591,6 +1609,17 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } else if(G.qual==LR_ALTKEY) { + if(G.f & G_WEIGHTPAINT) + ob= ob->parent; + if(ob && (ob->flag & OB_POSEMODE)) { + bArmature *arm= ob->data; + if( ELEM(arm->drawtype, ARM_B_BONE, ARM_ENVELOPE)) { + initTransform(TFM_BONESIZE, CTX_NONE); + Transform(); + break; + } + } + if(okee("Clear size")) { clear_object('s'); } diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 624808aa85a..ea11b17f26d 100755 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -47,18 +47,19 @@ #include "MEM_guardedalloc.h" +#include "DNA_armature_types.h" +#include "DNA_ipo_types.h" /* some silly ipo flag */ #include "DNA_listBase.h" -#include "DNA_userdef_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" /* PET modes */ #include "DNA_screen_types.h" /* area dimensions */ -#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_texture_types.h" +#include "DNA_userdef_types.h" #include "DNA_view3d_types.h" -#include "DNA_ipo_types.h" /* some silly ipo flag */ -#include "DNA_meshdata_types.h" -#include "DNA_mesh_types.h" #include "BIF_editview.h" /* arrows_move_cursor */ #include "BIF_gl.h" @@ -285,6 +286,10 @@ static char *transform_to_undostr(TransInfo *t) return "Push/Pull"; case TFM_CREASE: return "Crease"; + case TFM_BONESIZE: + return "Bone Width"; + case TFM_BONE_ENVELOPE: + return "Bone Envelope"; } return "Transform"; } @@ -361,29 +366,39 @@ static void transformEvent(unsigned short event, short val) { Trans.state = TRANS_CONFIRM; break; case GKEY: - restoreTransObjects(&Trans); - initTransModeFlags(&Trans, TFM_TRANSLATION); - initTranslation(&Trans); - Trans.redraw = 1; + /* only switch when... */ + if( ELEM3(Trans.mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) { + restoreTransObjects(&Trans); + initTransModeFlags(&Trans, TFM_TRANSLATION); + initTranslation(&Trans); + Trans.redraw = 1; + } break; case SKEY: - restoreTransObjects(&Trans); - initTransModeFlags(&Trans, TFM_RESIZE); - initResize(&Trans); - Trans.redraw = 1; - break; - case RKEY: - if (Trans.mode == TFM_ROTATION) { + /* only switch when... */ + if( ELEM3(Trans.mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) { restoreTransObjects(&Trans); - initTransModeFlags(&Trans, TFM_TRACKBALL); - initTrackball(&Trans); + initTransModeFlags(&Trans, TFM_RESIZE); + initResize(&Trans); + Trans.redraw = 1; } - else { - restoreTransObjects(&Trans); - initTransModeFlags(&Trans, TFM_ROTATION); - initRotation(&Trans); + break; + case RKEY: + /* only switch when... */ + if( ELEM4(Trans.mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { + + if (Trans.mode == TFM_ROTATION) { + restoreTransObjects(&Trans); + initTransModeFlags(&Trans, TFM_TRACKBALL); + initTrackball(&Trans); + } + else { + restoreTransObjects(&Trans); + initTransModeFlags(&Trans, TFM_ROTATION); + initRotation(&Trans); + } + Trans.redraw = 1; } - Trans.redraw = 1; break; case CKEY: if (G.qual & LR_ALTKEY) { @@ -595,7 +610,16 @@ void initTransform(int mode, int context) { initCrease(&Trans); break; case TFM_BONESIZE: - initBoneSize(&Trans); + { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */ + bArmature *arm= Trans.poseobj->data; + if(arm->drawtype==ARM_ENVELOPE) + initBoneEnvelope(&Trans); + else + initBoneSize(&Trans); + } + break; + case TFM_BONE_ENVELOPE: + initBoneEnvelope(&Trans); break; } } @@ -675,6 +699,13 @@ void initManipulator(int mode) Trans.state = TRANS_RUNNING; Trans.context = CTX_NONE; + + /* automatic switch to scaling bone envelopes */ + if(mode==TFM_RESIZE && G.obedit && G.obedit->type==OB_ARMATURE) { + bArmature *arm= G.obedit->data; + if(arm->drawtype==ARM_ENVELOPE) + mode= TFM_BONE_ENVELOPE; + } initTrans(&Trans); // internal data, mouse, vectors @@ -2251,13 +2282,13 @@ void Mirror(short mode) scrarea_queue_headredraw(curarea); } -/* ******************** EditBone scaling *************** */ +/* ******************** EditBone (B-bone) width scaling *************** */ static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) { float tmat[3][3], smat[3][3], oldy; float sizemat[3][3]; - + Mat3MulMat3(smat, mat, td->mtx); Mat3MulMat3(tmat, td->smtx, smat); @@ -2357,10 +2388,86 @@ void initBoneSize(TransInfo *t) t->snap[2] = t->snap[1] * 0.1f; t->transform = BoneSize; t->fac = (float)sqrt( (float)( - (t->center2d[1] - t->imval[1])*(t->center2d[1] - t->imval[1]) - + - (t->center2d[0] - t->imval[0])*(t->center2d[0] - t->imval[0]) - ) ); + (t->center2d[1] - t->imval[1])*(t->center2d[1] - t->imval[1]) + + + (t->center2d[0] - t->imval[0])*(t->center2d[0] - t->imval[0]) + ) ); + + if(t->fac==0.0f) t->fac= 1.0f; // prevent Inf +} + +/* ******************** EditBone envelope *************** */ + +int BoneEnvelope(TransInfo *t, short mval[2]) +{ + TransData *td = t->data; + float ratio; + int i; + char str[50]; + + if(t->flag & T_SHIFT_MOD) { + /* calculate ratio for shiftkey pos, and for total, and blend these for precision */ + float dx= (float)(t->center2d[0] - t->shiftmval[0]); + float dy= (float)(t->center2d[1] - t->shiftmval[1]); + ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; + + dx= (float)(t->center2d[0] - mval[0]); + dy= (float)(t->center2d[1] - mval[1]); + ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio); + + } + else { + float dx= (float)(t->center2d[0] - mval[0]); + float dy= (float)(t->center2d[1] - mval[1]); + ratio = (float)sqrt( dx*dx + dy*dy)/t->fac; + } + + snapGrid(t, &ratio); + + applyNumInput(&t->num, &ratio); + + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[20]; + + outputNumInput(&(t->num), c); + sprintf(str, "Envelope: %s", c); + } + else { + sprintf(str, "Envelope: %3f", ratio); + } + + for(i = 0 ; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if(td->val) *td->val= td->ival*ratio; + } + + recalcData(t); + + headerprint(str); + + force_draw(0); + + if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); + + return 1; +} + +void initBoneEnvelope(TransInfo *t) +{ + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; + t->transform = BoneEnvelope; + t->fac = (float)sqrt( (float)( + (t->center2d[1] - t->imval[1])*(t->center2d[1] - t->imval[1]) + + + (t->center2d[0] - t->imval[0])*(t->center2d[0] - t->imval[0]) + ) ); if(t->fac==0.0f) t->fac= 1.0f; // prevent Inf } diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index a4ddf8d7096..88c0ce02452 100755 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -446,6 +446,22 @@ static int add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tra Mat3MulMat3(td->axismtx, omat, pmat); Mat3Ortho(td->axismtx); + if(t->mode==TFM_BONESIZE) { + bArmature *arm= t->poseobj->data; + + if(arm->drawtype==ARM_ENVELOPE) { + td->loc= NULL; + td->val= &bone->dist; + td->ival= bone->dist; + } + else { + // abusive storage of scale in the loc pointer :) + td->loc= &bone->xwidth; + VECCOPY (td->iloc, td->loc); + td->val= NULL; + } + } + return 1; } } @@ -466,9 +482,11 @@ static void createTransPose(Object *ob, TransInfo *t) arm=get_armature (ob); if (arm==NULL || ob->pose==NULL) return; - if (arm->flag & ARM_RESTPOS){ - notice ("Pose edit not possible while Rest Position is enabled"); - return; + if (arm->flag & ARM_RESTPOS) { + if(t->mode!=TFM_BONESIZE) { + notice ("Pose edit not possible while Rest Position is enabled"); + return; + } } if (!(ob->lay & G.vd->lay)) return; @@ -507,6 +525,7 @@ static void createTransPose(Object *ob, TransInfo *t) static void createTransArmatureVerts(TransInfo *t) { EditBone *ebo; + bArmature *arm= G.obedit->data; TransData *td; float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3]; @@ -532,11 +551,57 @@ static void createTransArmatureVerts(TransInfo *t) td = t->data = MEM_mallocN(t->total*sizeof(TransData), "TransEditBone"); for (ebo=G.edbo.first;ebo;ebo=ebo->next){ - if (t->mode==TFM_BONESIZE) { + + ebo->oldlength= ebo->length; // might be used for scaling + + if (t->mode==TFM_BONE_ENVELOPE) { + + if (ebo->flag & BONE_ROOTSEL){ + td->val= &ebo->rad_head; + td->ival= *td->val; + + VECCOPY (td->center, ebo->head); + td->flag= TD_SELECTED; + + Mat3CpyMat3(td->smtx, smtx); + Mat3CpyMat3(td->mtx, mtx); + + td->loc = NULL; + td->ext = NULL; + td->tdi = NULL; + + td++; + } + if (ebo->flag & BONE_TIPSEL){ + td->val= &ebo->rad_tail; + td->ival= *td->val; + VECCOPY (td->center, ebo->tail); + td->flag= TD_SELECTED; + + Mat3CpyMat3(td->smtx, smtx); + Mat3CpyMat3(td->mtx, mtx); + + td->loc = NULL; + td->ext = NULL; + td->tdi = NULL; + + td++; + } + + } + else if (t->mode==TFM_BONESIZE) { if (ebo->flag & BONE_SELECTED) { - // abusive storage of scale in the loc pointer :) - td->loc= &ebo->xwidth; - VECCOPY (td->iloc, td->loc); + if(arm->drawtype==ARM_ENVELOPE) { + td->loc= NULL; + td->val= &ebo->dist; + td->ival= ebo->dist; + } + else { + // abusive storage of scale in the loc pointer :) + td->loc= &ebo->xwidth; + VECCOPY (td->iloc, td->loc); + td->val= NULL; + } VECCOPY (td->center, ebo->head); td->flag= TD_SELECTED; @@ -551,7 +616,6 @@ static void createTransArmatureVerts(TransInfo *t) td->ext = NULL; td->tdi = NULL; - td->val = NULL; td++; } @@ -1363,7 +1427,10 @@ void special_aftertrans_update(TransInfo *t) int redrawipo=0; int cancelled= (t->state == TRANS_CANCEL); - if(G.obedit); // nothing + if(G.obedit) { + if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE) + allqueue(REDRAWBUTSEDIT, 0); + } else if( (t->flag & T_POSE) && t->poseobj) { bArmature *arm; bAction *act; @@ -1415,6 +1482,10 @@ void special_aftertrans_update(TransInfo *t) ob->recalc= 0; // is set on OK position already by recalcData() } /* do not call DAG_object_flush_update always, we dont want actions to update, for inserting keys */ + + if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE) + allqueue(REDRAWBUTSEDIT, 0); + } else { base= FIRSTBASE; @@ -1636,10 +1707,11 @@ void createTransData(TransInfo *t) } t->flag |= T_EDIT; - /* exception... hackish, we want bonescale to use bone orientation matrix (ton) */ + /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */ if(t->mode==TFM_BONESIZE) { t->flag &= ~T_EDIT; t->flag |= T_POSE; + t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */ } } else if (ob && (ob->flag & OB_POSEMODE)) { diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index d938b43299d..9ab175d2681 100755 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -127,12 +127,16 @@ static void transform_armature_mirror_update(void) eboflip->tail[0]= -ebo->tail[0]; eboflip->tail[1]= ebo->tail[1]; eboflip->tail[2]= ebo->tail[2]; + eboflip->rad_tail= ebo->rad_tail; } if(ebo->flag & BONE_ROOTSEL) { eboflip->head[0]= -ebo->head[0]; eboflip->head[1]= ebo->head[1]; eboflip->head[2]= ebo->head[2]; + eboflip->rad_head= ebo->rad_head; } + if(ebo->flag & BONE_SELECTED) + eboflip->dist= ebo->dist; } } } @@ -176,6 +180,17 @@ void recalcData(TransInfo *t) VECCOPY (ebo->parent->tail, ebo->head); } } + + if(arm->drawtype==ARM_ENVELOPE) { + if(ebo->oldlength==0.0f) { + ebo->rad_head= 0.25f*ebo->length; + ebo->rad_tail= 0.10f*ebo->length; + if(ebo->parent) { + if(ebo->rad_head > ebo->parent->rad_tail) + ebo->rad_head= ebo->parent->rad_tail; + } + } + } } if(arm->flag & ARM_MIRROR_EDIT) transform_armature_mirror_update(); @@ -260,9 +275,8 @@ void initTransModeFlags(TransInfo *t, int mode) t->flag |= T_NO_CONSTRAINT; break; case TFM_SHEAR: - t->flag |= T_NO_CONSTRAINT; - break; case TFM_CREASE: + case TFM_BONE_ENVELOPE: t->flag |= T_NO_CONSTRAINT; break; } diff --git a/source/blender/src/view.c b/source/blender/src/view.c index ba70a06489a..9b3eab557d0 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -809,6 +809,7 @@ void setwinmatrixview3d(rctf *rect) /* rect: for picking */ else y1= -G.vd->dist; y2= -y1; + far*= 0.5; // otherwise too extreme low zbuffer quality near= -far; orth= 1; } |