More armature goodies;
authorTon Roosendaal <ton@blender.org>
Sat, 16 Jul 2005 19:07:02 +0000 (19:07 +0000)
committerTon Roosendaal <ton@blender.org>
Sat, 16 Jul 2005 19:07:02 +0000 (19:07 +0000)
The B-Bones!
(where the B can be read as 'block' or 'bezier' or 'b-spline')

- set option on/off in edit buttons, armature panel
- scaling of B-bones only works in editmode, use ALT+S to make bones fatter
  or thinner. Also works for constrainted transform
- In pose mode, you now have a buttons panel with per-bone settings too
  Here you can find the "segments" button, which allows bones to
  interpolate between previous/next bones, including roll.
- Buttons to control interpolation ("In" and "Out" are disabled, doesn't
  work satisfying yet

NOTE: this doesn't give deform yet! Main purpose for now is to test if this
drawing method serves to animate/pose armatures well.
Still need to review proper interpolation methods... maybe bezier is too
limited.

22 files changed:
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/displist.c
source/blender/blenloader/intern/readfile.c
source/blender/include/BIF_editarmature.h
source/blender/include/BIF_transform.h
source/blender/include/transform.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_armature_types.h
source/blender/src/buttons_editing.c
source/blender/src/drawarmature.c
source/blender/src/drawipo.c
source/blender/src/drawobject.c
source/blender/src/editarmature.c
source/blender/src/editview.c
source/blender/src/resources.c
source/blender/src/space.c
source/blender/src/transform.c
source/blender/src/transform_conversions.c
source/blender/src/usiblender.c

index 3b924b56c4716b73ff3f604a75963994fc80611e..5b71c5a5917298fb5542bfa212d858f86c6df2ef 100644 (file)
@@ -87,6 +87,7 @@ void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone);
 void armature_rebuild_pose(struct Object *ob, struct bArmature *arm);
 void where_is_pose (struct Object *ob);
 
+/* get_objectspace_bone_matrix has to be removed still */
 void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed);
 void vec_roll_to_mat3(float *vec, float roll, float mat[][3]);
 
@@ -103,7 +104,13 @@ void GB_calc_armature_deform (float *co, struct MDeformVert *dvert);
 void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4]);
 void GB_validate_defgroups (struct Mesh *mesh, struct ListBase *defbase);
 
-/*void make_boneParentMatrix (struct Bone* bone, float mat[][4]);*/ 
+/* B-Bone support */
+typedef struct Mat4 {
+       float mat[4][4];
+} Mat4;
+
+Mat4 *b_bone_spline_setup(struct bPoseChannel *pchan);
+
 
 #ifdef __cplusplus
 }
index 7b76a438e59cdf3286dd0218c8beae8d8f1d6c96..709b7b1c811c07b5ab184dcf9968b58ee9c015d6 100644 (file)
@@ -69,7 +69,7 @@ void basisNurb(float t, short order, short pnts, float *knots, float *basis, int
 void makeNurbfaces( struct Nurb *nu, float *data);
 void makeNurbcurve_forw(struct Nurb *nu, float *data);
 void makeNurbcurve( struct Nurb *nu, float *data, int dim);
-void maakbez(float q0, float q1, float q2, float q3, float *p, int it);
+void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
 void make_orco_surf( struct Curve *cu);
 void makebevelcurve( struct Object *ob,  struct ListBase *disp);
 short bevelinside(struct BevList *bl1,struct BevList *bl2);
index bac11a3646d29f46eadcb34a59ae7048d299457c..7cd0e7d0f91569637c0b166b4fa1775a9006a3f1 100644 (file)
@@ -45,6 +45,7 @@
 #include "DNA_view3d_types.h"
 #include "DNA_constraint_types.h"
 
+#include "BKE_curve.h"
 #include "BKE_depsgraph.h"
 #include "BKE_displist.h"
 #include "BKE_global.h"
@@ -242,6 +243,107 @@ Bone *get_named_bone (bArmature *arm, const char *name)
        return bone;
 }
 
+/* ************* B-Bone support ******************* */
+
+#define MAX_BBONE_SUBDIV       32
+
+/* returns pointer to static array, filled with desired amount of bone->segments elements */
+/* this calculation is done within pchan pose_mat space */
+Mat4 *b_bone_spline_setup(bPoseChannel *pchan)
+{
+       static Mat4 bbone_array[MAX_BBONE_SUBDIV];
+       bPoseChannel *next, *prev;
+       Bone *bone= pchan->bone;
+       float h1[3], h2[3], length, hlength, roll;
+       float mat3[3][3], imat[4][4];
+       float data[MAX_BBONE_SUBDIV+1][4], *fp;
+       int a;
+       
+       length= bone->length;
+       hlength= length*0.390464f;              // 0.5*sqrt(2)*kappa, the handle length for near-perfect circles
+       
+       /* evaluate next and prev bones */
+       if(bone->flag & BONE_IK_TOPARENT)
+               prev= pchan->parent;
+       else
+               prev= NULL;
+       
+       next= pchan->child;
+       
+       /* find the handle points, since this is inside bone space, the 
+               first point = (0,0,0)
+               last point =  (0, length, 0) */
+       
+       Mat4Invert(imat, pchan->pose_mat);
+       
+       if(prev) {
+               /* transform previous point inside this bone space */
+               VECCOPY(h1, prev->pose_head);
+               Mat4MulVecfl(imat, h1);
+               /* if previous bone is B-bone too, use average handle direction */
+               if(prev->bone->segments>1) h1[1]-= length;
+               Normalise(h1);
+               VecMulf(h1, -hlength);
+       }
+       else {
+               h1[0]= 0.0f; h1[1]= hlength; h1[2]= 0.0f;
+       }
+       if(next) {
+               float difmat[4][4], result[3][3], imat3[3][3];
+               
+               /* transform next point inside this bone space */
+               VECCOPY(h2, next->pose_tail);
+               Mat4MulVecfl(imat, h2);
+               /* if next bone is B-bone too, use average handle direction */
+               if(next->bone->segments>1);
+               else h2[1]-= length;
+               
+               /* find the next roll to interpolate as well */
+               Mat4MulMat4(difmat, next->pose_mat, imat);
+               Mat3CpyMat4(result, difmat);                            // the desired rotation at beginning of next bone
+               
+               vec_roll_to_mat3(h2, 0.0f, mat3);                       // the result of vec_roll without roll
+               
+               Mat3Inv(imat3, mat3);
+               Mat3MulMat3(mat3, imat3, result);                       // the matrix transforming vec_roll to desired roll
+               
+               roll= atan2(mat3[2][0], mat3[2][2]);
+               
+               /* and only now negate handle */
+               Normalise(h2);
+               VecMulf(h2, -hlength);
+               
+       }
+       else {
+               h2[0]= 0.0f; h2[1]= -hlength; h2[2]= 0.0f;
+               roll= 0.0;
+       }
+       
+       //      VecMulf(h1, pchan->bone->ease1);
+       //      VecMulf(h2, pchan->bone->ease2);
+       
+       /* make curve */
+       if(bone->segments > MAX_BBONE_SUBDIV)
+               bone->segments= MAX_BBONE_SUBDIV;
+       
+       forward_diff_bezier(0.0, h1[0],         h2[0],                  0.0,            data[0],        bone->segments, 4);
+       forward_diff_bezier(0.0, h1[1],         length + h2[1], length,         data[0]+1,      bone->segments, 4);
+       forward_diff_bezier(0.0, h1[2],         h2[2],                  0.0,            data[0]+2,      bone->segments, 4);
+       
+       forward_diff_bezier(0.0, 0.390464f*roll, (1.0f-0.390464f)*roll, roll,   data[0]+3,      bone->segments, 4);
+       
+       /* make transformation matrices for the segments for drawing */
+       
+       for(a=0, fp= data[0]; a<bone->segments; a++, fp+=4) {
+               VecSubf(h1, fp+4, fp);
+               vec_roll_to_mat3(h1, fp[3], mat3);              // fp[3] is roll
+               Mat4CpyMat3(bbone_array[a].mat, mat3);
+               VECCOPY(bbone_array[a].mat[3], fp);
+       }
+       
+       return bbone_array;
+}
+
 /* ************ Armature Deform ******************* */
 
 void init_armature_deform(Object *parent, Object *ob)
@@ -521,6 +623,13 @@ void where_is_armature_bone(Bone *bone, Bone *prevbone)
 
        bone->length= VecLenf(bone->head, bone->tail);
        
+       /* this is called on old file reading too... */
+       if(bone->xwidth==0.0) {
+               bone->xwidth= 0.1f;
+               bone->zwidth= 0.1f;
+               bone->segments= 1;
+       }
+       
        if(prevbone) {
                float offs_bone[4][4];  // yoffs(b-1) + root(b) + bonemat(b)
                
@@ -567,17 +676,20 @@ void where_is_armature (bArmature *arm)
        }
 }
 
-static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int depth, int counter)
+static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int counter)
 {
        bPoseChannel *pchan = verify_pose_channel (pose, bone->name);   // verify checks and/or adds
 
        pchan->bone= bone;
        pchan->parent= parchan;
-       pchan->depth= depth;
+       
        counter++;
        
        for(bone= bone->childbase.first; bone; bone= bone->next) {
-               counter= rebuild_pose_bone(pose, bone, pchan, depth+1, counter);
+               counter= rebuild_pose_bone(pose, bone, pchan, counter);
+               /* for quick detecting of next bone in chain */
+               if(bone->flag & BONE_IK_TOPARENT)
+                       pchan->child= get_pose_channel(pose, bone->name);
        }
        
        return counter;
@@ -596,9 +708,9 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
        if(ob->pose==NULL) ob->pose= MEM_callocN(sizeof(bPose), "new pose");
        pose= ob->pose;
        
-       /* first step, check if all channels are there, also sets depth */
+       /* first step, check if all channels are there */
        for(bone= arm->bonebase.first; bone; bone= bone->next) {
-               counter= rebuild_pose_bone(pose, bone, NULL, 0, counter);
+               counter= rebuild_pose_bone(pose, bone, NULL, counter);
        }
        /* sort channels on dependency order, so we can walk the channel list */
 
index 98aa41b392e786cf47f89b166a806248079aaa08..7dd8c6efd65298f18ecad9cba1a66ebc183a3cab 100644 (file)
@@ -1055,7 +1055,8 @@ void makeNurbcurve(Nurb *nu, float *data, int dim)
        MEM_freeN(basisu);
 }
 
-void maakbez(float q0, float q1, float q2, float q3, float *p, int it)
+/* forward differencing method for bezier curve */
+void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
 {
        float rt0,rt1,rt2,rt3,f;
        int a;
@@ -1075,7 +1076,7 @@ void maakbez(float q0, float q1, float q2, float q3, float *p, int it)
   
        for(a=0; a<=it; a++) {
                *p= q0;
-               p+= 3;
+               p+= stride;
                q0+= q1;
                q1+= q2;
                q2+= q3;
@@ -1612,9 +1613,9 @@ void makeBevelList(Object *ob)
                                                v2= bezt->vec[0];
                                                
                                                /* always do all three, to prevent data hanging around */
-                                               maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu);
-                                               maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu);
-                                               maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu);
+                                               forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], data, nu->resolu, 3);
+                                               forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu, 3);
+                                               forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu, 3);
                                                
                                                if((nu->type & CU_2D)==0) {
                                                        if(cu->flag & CU_3D) {
index 874bec746f1567722eecea3dc77cf44f40f9212b..0532456c97b3fd337493dbdf2049d30108671f52 100644 (file)
@@ -1251,7 +1251,7 @@ static void curve_to_displist(ListBase *nubase, ListBase *dispbase)
                                }
                                
                                dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
-                               /* len+1 because of 'maakbez' function */
+                               /* len+1 because of 'forward_diff_bezier' function */
                                dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
                                BLI_addtail(dispbase, dl);
                                dl->parts= 1;
@@ -1283,10 +1283,10 @@ static void curve_to_displist(ListBase *nubase, ListBase *dispbase)
                                        else {
                                                v1= prevbezt->vec[1];
                                                v2= bezt->vec[0];
-                                               maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu);
-                                               maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu);
+                                               forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], data, nu->resolu, 3);
+                                               forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu, 3);
                                                if((nu->type & 8)==0)
-                                                       maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu);
+                                                       forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu, 3);
                                                data+= 3*nu->resolu;
                                        }
                                        
index 25cab6cf8bb20aea51094f09953f46fdea01dfef..42a9f49ee2ea81e5e2150758ebe67790d384dd70 100644 (file)
@@ -2265,6 +2265,7 @@ static void direct_link_pose(FileData *fd, bPose *pose) {
        for (chan = pose->chanbase.first; chan; chan=chan->next) {
                chan->bone= NULL;
                chan->parent= newdataadr(fd, chan->parent);
+               chan->child= newdataadr(fd, chan->child);
                direct_link_constraints(fd, &chan->constraints);
        }
 
index 056888e33f6a3f31fca82542dd6780945d7fe872..b0b6147f564a7254801962ef42998c4f56511825 100644 (file)
@@ -64,8 +64,10 @@ typedef struct EditBone
                for pose element, rather than trying to use the existing transObject
                system?
        */
-       float dist, weight, length;
-       short boneclass;
+       float dist, weight;
+       float xwidth, length, zwidth;   /* put them in order! transform uses this as scale */
+       float ease1, ease2;
+       short boneclass, segments;
 
 
 } EditBone;
index e8bdc8c2e307c8c1b20c2397e3a8fd724e38684f..57aaf37a65dcc88ff4907e77526a37295aafdb4b 100755 (executable)
@@ -50,6 +50,7 @@
 #define TFM_PUSHPULL           12
 #define TFM_CREASE                     13
 #define TFM_MIRROR                     14
+#define TFM_BONESIZE           15
 
 /* TRANSFORM CONTEXTS */
 #define CTX_NONE                       0
index 69e9f1d919ccb429fdc67f663b33491e8405e6c8..b776bd26c1a4019bcc340472e5644405d3b85064 100755 (executable)
@@ -246,6 +246,9 @@ int PushPull(TransInfo *t, short mval[2]);
 void initCrease(TransInfo *t);
 int Crease(TransInfo *t, short mval[2]);
 
+void initBoneSize(TransInfo *t);
+int BoneSize(TransInfo *t, short mval[2]);
+
 /*********************** transform_conversions.c ********** */
 struct ListBase;
 void count_bone_select(TransInfo *t, struct ListBase *lb, int do_it);
index f88d298e5ee6e4364303eac37a7b5f704cefe897..4cb4f1dd1a2f2b67e11ecb40efe9c792ae22f640 100644 (file)
@@ -51,12 +51,14 @@ typedef struct bPoseChannel {
        struct bPoseChannel     *next, *prev;
        ListBase                        constraints;
        char                            name[32];       /* Channels need longer names than normal blender objects */
+       
        short                           flag;           /* dynamic, for detecting transform changes */
        short                           constflag;  /* for quick detecting which constraints affect this channel */
-       int                                     depth;          /* dependency sorting help */
+       int                                     pad;
        
        struct Bone                     *bone;          /* set on read file or rebuild pose */
        struct bPoseChannel *parent;    /* set on read file or rebuild pose */
+       struct bPoseChannel *child;             /* set on read file or rebuild pose, the 'ik' child, for b-bones */
        struct ListBase          chain;         /* only while evaluating pose */
        
        float           loc[3];                         /* written in by actions or transform */
@@ -69,7 +71,7 @@ typedef struct bPoseChannel {
        
        float           pose_head[3];           /* actually pose_mat[3] */
        float           pose_tail[3];           /* also used for drawing help lines... */
-       int pad;
+       int pad1;
 } bPoseChannel;
 
 
index 437a5c6a4e30800169e1d19f2f45c8961b23a2be..cfda7b6026204d397c54e59ac912ba69f5cca8e3 100644 (file)
@@ -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;   /* */
+       float                   roll, length;   /*  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,11 +60,13 @@ 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 for non-deformgroup deforms */
+       float                   dist, weight;   /*  dist, weight: for non-deformgroup deforms */
+       float                   xwidth, zwidth; /*  width: for block bones */
+       float                   ease1, ease2;   /*  length of bezier handles */
        
-       float size[3];                                  /* patch for upward compat, UNUSED! */
-       short boneclass;
-       short pad1;
+       float                   size[3];                /*  patch for upward compat, UNUSED! */
+       short                   boneclass;
+       short                   segments;               /*  for B-bones */
 }Bone;
 
 typedef struct bArmature {
@@ -99,6 +101,8 @@ typedef struct bArmature {
 #define                ARM_DELAYDEFORM 0x0040
 #define                ARM_DONT_USE    0x0080
 #define                ARM_NO_ACTION   0x0100
+#define                ARM_B_BONES             0x0200
+
 
 /* bone->flag */
 #define                BONE_SELECTED   1
index d5eca3c8a0a3d4d920e2287c2ad6e5e749640cde..65b634fe525063fcd0da37fbc59f37ba5ca164cf 100644 (file)
@@ -1764,6 +1764,23 @@ void validate_editbonebutton_cb(void *bonev, void *namev)
        allqueue(REDRAWALL, 0);
 }
 
+/* assumes armature posemode */
+static void validate_posebonebutton_cb(void *bonev, void *namev)
+{
+       Bone *bone= bonev;
+       Object *ob= OBACT;
+       char oldname[32], newname[32];
+       
+       /* need to be on the stack */
+       BLI_strncpy(newname, bone->name, 32);
+       BLI_strncpy(oldname, (char *)namev, 32);
+       /* restore */
+       BLI_strncpy(bone->name, oldname, 32);
+       
+       armature_bone_rename(ob->data, oldname, newname); // editarmature.c
+       allqueue(REDRAWALL, 0);
+}
+
 static void armature_rest_pos_func(void *pointer1, void *pointer2) 
 {
        Object *ob= pointer1;
@@ -1775,7 +1792,7 @@ static void editing_panel_armature_type(Object *ob, bArmature *arm)
 {
        uiBlock         *block;
        uiBut       *but;
-       int                     bx=148, by=100;
+       int                     bx=148, by=120;
 
        block= uiNewBlock(&curarea->uiblocks, "editing_panel_armature_type", UI_EMBOSS, UI_HELV, curarea->win);
        if(uiNewPanel(curarea, block, "Armature", "Editing", 320, 0, 318, 204)==0) return;
@@ -1784,14 +1801,15 @@ static void editing_panel_armature_type(Object *ob, bArmature *arm)
                                        "Rest Pos", bx,by,97,20, &arm->flag, 0, 0, 0, 0,
                                        "Disable all animation for this object");
        uiButSetFunc(but, armature_rest_pos_func, ob, arm);
-
+       
+       by-= 23;
        uiBlockBeginAlign(block);
-       uiDefButI(block, TOG|BIT|ARM_DRAWAXESBIT,REDRAWVIEW3D, "Draw Axes", bx,by-46,97,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes");
+       uiDefButBitI(block, TOG, ARM_B_BONES, REDRAWVIEW3D, "B-Bones", bx, by-23,97,20, &arm->flag, 0, 0, 0, 0, "Draw bone as boxes, showing subdivision and b-splines");
+       uiDefButI(block, TOG|BIT|ARM_DRAWAXESBIT,REDRAWVIEW3D, "Draw Axes", bx, by-46,97,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes");
        uiDefButI(block, TOG|BIT|ARM_DRAWNAMESBIT,REDRAWVIEW3D, "Draw Names", bx,by-69,97,20, &arm->flag, 0, 0, 0, 0, "Draw bone names");
-       uiDefButBitC(block, TOG, OB_DRAWXRAY,REDRAWVIEW3D, "X-Ray", bx,by-92,97,20, &ob->dtx, 0, 0, 0, 0, "Draw armature in front of solid objects");
-       uiDefButI(block, TOG|BIT|ARM_DELAYBIT,REDRAWVIEW3D,
-                         "Delay Deform", bx,by-115,97,20, &arm->flag, 0, 0, 0, 0,
-                         "Don't deform children when manipulating bones in pose mode");
+       uiDefButBitC(block, TOG, OB_DRAWXRAY,REDRAWVIEW3D, "X-Ray", bx, by-92,97,20, &ob->dtx, 0, 0, 0, 0, "Draw armature in front of solid objects");
+       uiDefButI(block, TOG|BIT|ARM_DELAYBIT,REDRAWVIEW3D, "Delay Deform", bx, by-115,97,20, &arm->flag, 0, 0, 0, 0, "Don't deform children when manipulating bones in pose mode");
+
 }
 
 static void editing_panel_armature_bones(Object *ob, bArmature *arm)
@@ -1845,13 +1863,9 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm)
 
                        /* Dist and weight buttons */
                        uiBlockBeginAlign(block);
-                       but=uiDefButS(block, MENU, REDRAWVIEW3D,
-                                                       "Skinnable %x0|" "Unskinnable %x1|" "Head %x2|"
-                                                       "Neck %x3|" "Back %x4|" "Shoulder %x5|" "Arm %x6|"
-                                                       "Hand %x7|" "Finger %x8|" "Thumb %x9|" "Pelvis %x10|"
-                                                       "Leg %x11|" "Foot %x12|" "Toe %x13|" "Tentacle %x14",
-                                                       bx-10,by-19,117,18, &curBone->boneclass, 0.0, 0.0, 0.0, 0.0,
-                                                       "Classification of armature element");
+                       uiDefButS(block, NUM, REDRAWVIEW3D, "Segm: ",
+                                                       bx-10,by-19,117,18, &curBone->segments, 1.0, 32.0, 0.0, 0.0,
+                                                       "Subdivisions for B-bones");
 
                        /* Dist and weight buttons */
                        uiDefButF(block, NUM,REDRAWVIEW3D, "Dist:", bx+110, by-19,
@@ -1872,6 +1886,67 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm)
 
 }
 
+static void editing_panel_pose_bones(Object *ob, bArmature *arm)
+{
+       uiBlock         *block;
+       uiBut           *but;
+       bPoseChannel *pchan;
+       Bone            *curBone;
+       int                     bx=148, by=180;
+       int                     index;
+       
+       /* Draw the bone name block */
+       
+       block= uiNewBlock(&curarea->uiblocks, "editing_panel_pose_bones", UI_EMBOSS, UI_HELV, curarea->win);
+       if(uiNewPanel(curarea, block, "Armature Bones", "Editing", 640, 0, 318, 204)==0) return;
+       
+       /* this is a variable height panel, newpanel doesnt force new size on existing panels */
+       /* so first we make it default height */
+       uiNewPanelHeight(block, 204);
+       
+       uiDefBut(block, LABEL, 0, "Selected Bones", bx,by,158,18, 0, 0, 0, 0, 0, "Only show in Armature Editmode/Posemode");
+       by-=20;
+       for (pchan=ob->pose->chanbase.first, index=0; pchan; pchan=pchan->next, index++){
+               curBone= pchan->bone;
+               if (curBone->flag & (BONE_SELECTED)) {
+                       
+                       /* Hide in posemode flag */
+                       uiDefButI(block, TOG|BIT|BONE_HIDDENBIT, REDRAWVIEW3D, "Hide", bx-55,by,45,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode");
+                       
+                       /*      Bone naming button */
+                       uiBlockBeginAlign(block);
+                       but=uiDefBut(block, TEX, REDRAWVIEW3D, "BO:", bx-10,by,117,18, &curBone->name, 0, 24, 0, 0, "Change the bone name");
+                       uiButSetFunc(but, validate_posebonebutton_cb, curBone, NULL);
+                       
+                       /* Dist and weight buttons */
+                       uiDefButF(block, NUM,REDRAWVIEW3D, "Dist:", bx+107, by,
+                                         105, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0,
+                                         "Bone deformation distance");
+                       uiDefButF(block, NUM,REDRAWVIEW3D, "Weight:", bx+220, by,
+                                         110, 18, &curBone->weight, 0.0F, 1000.0F,
+                                         10.0F, 0.0F, "Bone deformation weight");
+                       
+                       
+                       /* Segment, ease in/out buttons */
+                       uiBlockBeginAlign(block);
+                       uiDefButS(block, NUM, REDRAWVIEW3D, "Segm: ",
+                                         bx-10,by-19,117,19, &curBone->segments, 1.0, 32.0, 0.0, 0.0, "Subdivisions for B-bones");
+                       uiDefButF(block, NUM,REDRAWVIEW3D, "In:", 
+                                         bx+107, by-19,105, 19, &curBone->ease1, 0.0, 2.0, 10.0, 0.0, "First length of Bezier handle");
+                       uiDefButF(block, NUM,REDRAWVIEW3D, "Out:", 
+                                         bx+220, by-19, 110, 19, &curBone->ease2, 0.0, 2.0, 10.0, 0.0, "Second length of Bezier handle");
+                       
+                       uiBlockEndAlign(block);
+                       by-=42;
+               }
+       }
+       
+       if(by<0) {
+               uiNewPanelHeight(block, 204 - by);
+       }
+       
+}
+
 
 /* *************************** MESH ******************************** */
 
@@ -2806,6 +2881,9 @@ void editing_panels()
                if(G.obedit) {
                        editing_panel_armature_bones(ob, arm);
                }
+               else if(G.obpose==ob) {
+                       editing_panel_pose_bones(ob, arm);
+               }               
                break;
        }
        uiClearButLock();
index 4d474d65c9ba96a472203e36d553ca8f585ff041..cd29a5ff21d0410d6c20188d4daa9e164ccd3fea 100644 (file)
 #include "blendef.h"
 #include "nla.h"
 
+/* half the cube, in Y */
+static float cube[8][3] = {
+{-1.0,  0.0, -1.0},
+{-1.0,  0.0,  1.0},
+{-1.0,  1.0,  1.0},
+{-1.0,  1.0, -1.0},
+{ 1.0,  0.0, -1.0},
+{ 1.0,  0.0,  1.0},
+{ 1.0,  1.0,  1.0},
+{ 1.0,  1.0, -1.0},
+};
+
+
+/* *************** Armature drawing, helper calls for parts ******************* */
+
+static void drawsolidcube_size(float xsize, float ysize, float zsize)
+{
+       float n[3];
+       
+       glScalef(xsize, ysize, zsize);
+       
+       n[0]=0; n[1]=0; n[2]=0;
+       glBegin(GL_QUADS);
+       n[0]= -1.0;
+       glNormal3fv(n); 
+       glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+       n[0]=0;
+       glEnd();
+       
+       glBegin(GL_QUADS);
+       n[1]= -1.0;
+       glNormal3fv(n); 
+       glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
+       n[1]=0;
+       glEnd();
+       
+       glBegin(GL_QUADS);
+       n[0]= 1.0;
+       glNormal3fv(n); 
+       glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
+       n[0]=0;
+       glEnd();
+       
+       glBegin(GL_QUADS);
+       n[1]= 1.0;
+       glNormal3fv(n); 
+       glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+       n[1]=0;
+       glEnd();
+       
+       glBegin(GL_QUADS);
+       n[2]= 1.0;
+       glNormal3fv(n); 
+       glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
+       n[2]=0;
+       glEnd();
+       
+       glBegin(GL_QUADS);
+       n[2]= -1.0;
+       glNormal3fv(n); 
+       glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
+       glEnd();
+       
+}
+
+static void drawcube_size(float xsize, float ysize, float zsize)
+{
+       
+       glScalef(xsize, ysize, zsize);
+       
+       glBegin(GL_LINE_STRIP);
+       glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+       glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
+       glVertex3fv(cube[7]); glVertex3fv(cube[4]);
+       glEnd();
+       
+       glBegin(GL_LINE_STRIP);
+       glVertex3fv(cube[1]); glVertex3fv(cube[5]);
+       glEnd();
+       
+       glBegin(GL_LINE_STRIP);
+       glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+       glEnd();
+       
+       glBegin(GL_LINE_STRIP);
+       glVertex3fv(cube[3]); glVertex3fv(cube[7]);
+       glEnd();
+       
+}
 
-/* *************** Armature drawing ******************* */
 
 static void draw_bonevert(void)
 {
@@ -241,43 +329,25 @@ static void draw_bone_solid_octahedral(void)
        else glCallList(displist);
 }      
 
+/* *************** Armature drawing, bones ******************* */
+
 
-static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, char *name)
+static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id, float length)
 {
-       
-       /*      Draw a 3d octahedral bone, we use normalized space based on length,
-           for glDisplayLists */
-       
-       /* set up solid drawing */
-       if(dt > OB_WIRE) {
-               glEnable(GL_COLOR_MATERIAL);
-               glEnable(GL_LIGHTING);
-               BIF_ThemeColor(TH_BONE_SOLID);
-       }
-       
-       /* colors for posemode */
-       if (armflag & ARM_POSEMODE) {
-               if(dt==OB_WIRE) {
-                       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);
-               }
-               else 
-                       BIF_ThemeColor(TH_BONE_SOLID);
-       }
-       
        /*      Draw root point if we have no IK parent */
        if (!(boneflag & BONE_IK_TOPARENT)){
                if (id != -1)
                        glLoadName (id | BONESEL_ROOT);
-               if (armflag & ARM_EDITMODE) {
-                       if(dt<=OB_WIRE) {
+               
+               if(dt<=OB_WIRE) {
+                       if(armflag & ARM_EDITMODE) {
                                if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
                                else BIF_ThemeColor(TH_VERTEX);
                        }
-                       else 
-                               BIF_ThemeColor(TH_BONE_SOLID);
                }
+               else 
+                       BIF_ThemeColor(TH_BONE_SOLID);
+               
                if(dt>OB_WIRE) draw_bonevert_solid();
                else draw_bonevert();
        }
@@ -285,33 +355,164 @@ static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned
        /*      Draw tip point */
        if (id != -1)
                glLoadName (id | BONESEL_TIP);
-       if (armflag & ARM_EDITMODE) {
-               if(dt<=OB_WIRE) {
+       
+       if(dt<=OB_WIRE) {
+               if(armflag & ARM_EDITMODE) {
                        if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
                        else BIF_ThemeColor(TH_VERTEX);
                }
-               else 
-                       BIF_ThemeColor(TH_BONE_SOLID);
+       }
+       else {
+               BIF_ThemeColor(TH_BONE_SOLID);
        }
        
-       glTranslatef(0.0, 1.0, 0.0);
+       glTranslatef(0.0, length, 0.0);
        if(dt>OB_WIRE) draw_bonevert_solid();
        else draw_bonevert();
+       glTranslatef(0.0, -length, 0.0);
        
-       /*      Draw additional axes */
-       if (armflag & ARM_DRAWAXES){
-               drawaxes(0.25f);
+       if(length > 0.05f) length-= 0.05f;      // make vertices visible
+}
+
+static void draw_b_bone_boxes(int dt, bPoseChannel *pchan, float xwidth, float length, float zwidth)
+{
+       int segments= 0;
+       
+       if(pchan) segments= pchan->bone->segments;
+       
+       if(segments>1 && pchan) {
+               float dlen= length/(float)segments;
+               Mat4 *bbone= b_bone_spline_setup(pchan);
+               int a;
+               
+               for(a=0; a<segments; a++, bbone++) {
+                       glPushMatrix();
+                       glMultMatrixf(bbone->mat);
+                       if(dt==OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
+                       else drawcube_size(xwidth, dlen, zwidth);
+                       glPopMatrix();
+               }
+       }
+       else {
+               glPushMatrix();
+               if(dt==OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
+               else drawcube_size(xwidth, length, zwidth);
+               glPopMatrix();
        }
+}
+
+static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
+{
+       float xwidth, length, zwidth;
        
-       /* now draw the bone itself */
-       glTranslatef(0.0, -1.0, 0.0);
+       if(pchan) {
+               xwidth= pchan->bone->xwidth;
+               length= pchan->bone->length;
+               zwidth= pchan->bone->zwidth;
+       }
+       else {
+               xwidth= ebone->xwidth;
+               length= ebone->length;
+               zwidth= ebone->zwidth;
+       }
+       
+       /* draw points only if... */
+       if(armflag & ARM_EDITMODE) {
+               draw_bone_points(dt, armflag, boneflag, id, length);
+       }
+
+       /* colors for modes */
+       if (armflag & ARM_POSEMODE) {
+               if(dt==OB_WIRE) {
+                       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);
+               }
+               else 
+                       BIF_ThemeColor(TH_BONE_SOLID);
+       }
+       else if (armflag & ARM_EDITMODE) {
+               if(dt==OB_WIRE) {
+                       if (boneflag & BONE_ACTIVE) BIF_ThemeColor(TH_EDGE_SELECT);
+                       else if (boneflag & BONE_SELECTED) BIF_ThemeColorShade(TH_EDGE_SELECT, -20);
+                       else BIF_ThemeColor(TH_WIRE);
+               }
+               else 
+                       BIF_ThemeColor(TH_BONE_SOLID);
+       }
        
        if (id != -1) {
-               if (armflag & ARM_POSEMODE)
-                       glLoadName((GLuint) id);
-               else{
-                       glLoadName ((GLuint) id|BONESEL_BONE);
+               glLoadName ((GLuint) id|BONESEL_BONE);
+       }
+       
+       /* set up solid drawing */
+       if(dt > OB_WIRE) {
+               glEnable(GL_COLOR_MATERIAL);
+               glEnable(GL_LIGHTING);
+               BIF_ThemeColor(TH_BONE_SOLID);
+               
+               draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
+               
+               /* disable solid drawing */
+               glDisable(GL_COLOR_MATERIAL);
+               glDisable(GL_LIGHTING);
+       }
+       else {  // wire
+               if (armflag & ARM_POSEMODE){
+                       if(constflag) {
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                               glEnable(GL_BLEND);
+                               
+                               if(constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80);
+                               else if(constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
+                               else BIF_ThemeColor4(TH_BONE_POSE);     // PCHAN_HAS_ACTION 
+                               
+                               draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
+                               
+                               glDisable(GL_BLEND);
+                               
+                               /* restore colors */
+                               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_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth);              
+       }
+}
+
+static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id)
+{
+       
+       /*      Draw a 3d octahedral bone, we use normalized space based on length,
+           for glDisplayLists */
+       
+       /* set up solid drawing */
+       if(dt > OB_WIRE) {
+               glEnable(GL_COLOR_MATERIAL);
+               glEnable(GL_LIGHTING);
+               BIF_ThemeColor(TH_BONE_SOLID);
+       }
+       
+       /* colors for posemode */
+       if (armflag & ARM_POSEMODE) {
+               if(dt==OB_WIRE) {
+                       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);
                }
+               else 
+                       BIF_ThemeColor(TH_BONE_SOLID);
+       }
+       
+       
+       draw_bone_points(dt, armflag, boneflag, id, 1.0);
+       
+       /* now draw the bone itself */
+       
+       if (id != -1) {
+               glLoadName ((GLuint) id|BONESEL_BONE);
        }
        
        /* wire? */
@@ -327,8 +528,8 @@ static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned
                                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                                glEnable(GL_BLEND);
                                
-                               if(constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 100);
-                               else if(constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 100);
+                               if(constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80);
+                               else if(constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
                                else BIF_ThemeColor4(TH_BONE_POSE);     // PCHAN_HAS_ACTION 
                                        
                                draw_bone_solid_octahedral();
@@ -384,16 +585,19 @@ static void draw_pose_channels(Object *ob, int dt)
                                glPushMatrix();
                                glMultMatrixf(pchan->pose_mat);
                                
-                               /* scale the matrix to unit bone space */
-                               glScalef(bone->length, bone->length, bone->length);
-                                                               
                                /* catch exception for bone with hidden parent */
                                flag= bone->flag;
                                if(bone->parent && (bone->parent->flag & BONE_HIDDEN))
                                        flag &= ~BONE_IK_TOPARENT;
                                
-                               draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->name);
-                               
+                               if(arm->flag & ARM_B_BONES)
+                                       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);
+                               }
                                glPopMatrix();
                        }
                        if (index!= -1) index++;
@@ -433,9 +637,6 @@ static void draw_pose_channels(Object *ob, int dt)
                                glPushMatrix();
                                glMultMatrixf(pchan->pose_mat);
                                
-                               /* scale the matrix to unit bone space */
-                               glScalef(bone->length, bone->length, bone->length);
-                               
                                /* catch exception for bone with hidden parent */
                                flag= bone->flag;
                                if(bone->parent && (bone->parent->flag & BONE_HIDDEN))
@@ -446,7 +647,14 @@ static void draw_pose_channels(Object *ob, int dt)
                                if(pchan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE))
                                        constflag |= PCHAN_HAS_ACTION;
 
-                               draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->name);
+                               if(arm->flag & ARM_B_BONES)
+                                       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);
+                               }
                                
                                glPopMatrix();
                        }
@@ -458,8 +666,8 @@ static void draw_pose_channels(Object *ob, int dt)
                bglPolygonOffset(0.0);
        glDisable(GL_CULL_FACE);
 
-       /* finally names */
-       if(arm->flag & ARM_DRAWNAMES) {
+       /* finally names and axes */
+       if(arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {
                // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
                if((G.f & G_PICKSEL) == 0) {
                        float vec[3];
@@ -475,10 +683,20 @@ static void draw_pose_channels(Object *ob, int dt)
                                }
                                else if(dt > OB_WIRE) BIF_ThemeColor(TH_TEXT);
                                
-                               VecMidf(vec, pchan->pose_head, pchan->pose_tail);
-                               glRasterPos3fv(vec);
-                               BMF_DrawString(G.font, " ");
-                               BMF_DrawString(G.font, pchan->name);
+                               if (arm->flag & ARM_DRAWNAMES){
+                                       VecMidf(vec, pchan->pose_head, pchan->pose_tail);
+                                       glRasterPos3fv(vec);
+                                       BMF_DrawString(G.font, " ");
+                                       BMF_DrawString(G.font, pchan->name);
+                               }                               
+                               /*      Draw additional axes */
+                               if( (arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE) ){
+                                       glPushMatrix();
+                                       glMultMatrixf(pchan->pose_mat);
+                                       glTranslatef(0.0f, pchan->bone->length, 0.0f);
+                                       drawaxes(0.25f);
+                                       glPopMatrix();
+                               }
                        }
                        
                        if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
@@ -497,9 +715,7 @@ static void set_matrix_editbone(EditBone *eBone)
        
        glTranslatef (offset[0],offset[1],offset[2]);
        
-       delta[0]= eBone->tail[0]-eBone->head[0];        
-       delta[1]= eBone->tail[1]-eBone->head[1];        
-       delta[2]= eBone->tail[2]-eBone->head[2];
+       VecSubf(delta, eBone->tail, eBone->head);       
        
        eBone->length = sqrt (delta[0]*delta[0] + delta[1]*delta[1] +delta[2]*delta[2]);
        
@@ -508,90 +724,111 @@ static void set_matrix_editbone(EditBone *eBone)
                                
        glMultMatrixf (bmat);
        
-       /* scale the matrix to unit bone space */
-       glScalef(eBone->length, eBone->length, eBone->length);
-       
 }
 
-/* called from drawobject.c */
-void draw_armature(Object *ob, int dt)
+static void draw_ebones(Object *ob, int dt)
 {
+       EditBone        *eBone;
        bArmature *arm= ob->data;
+       unsigned int    index;
        
-       /* 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 we're in editmode, draw the Global edit data */
-       if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) {
-               EditBone        *eBone;
-               unsigned int    index;
-               
-               if(ob==G.obedit) arm->flag |= ARM_EDITMODE;
-               
-               /* if solid we draw it first */
-               if(dt>OB_WIRE && (arm->flag & ARM_EDITMODE)) {
-                       for (eBone=G.edbo.first; eBone; eBone=eBone->next){
-                               glPushMatrix();
-                               set_matrix_editbone(eBone);
-                               
-                               draw_bone(OB_SOLID, arm->flag, eBone->flag, 0, -1, eBone->name);
-                               glPopMatrix();
-                       }
-               }
-               
-               /* if wire over solid, set offset */
-               if (dt>OB_WIRE) bglPolygonOffset(1.0);
-               
+       /* if solid we draw it first */
+       if(dt>OB_WIRE) {
                for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){
-                       
                        glPushMatrix();
                        set_matrix_editbone(eBone);
                        
-                       draw_bone(OB_WIRE, arm->flag, eBone->flag, 0, index, eBone->name);
-                       glPopMatrix();
-                       
-                       /* offset to parent */
-                       if (eBone->parent) {
-                               BIF_ThemeColor(TH_WIRE);
-                               glLoadName (-1);
-                               setlinestyle(3);
-                               
-                               glBegin(GL_LINES);
-                               glVertex3fv(eBone->parent->tail);
-                               glVertex3fv(eBone->head);
-                               glEnd();
-
-                               setlinestyle(0);
+                       if(arm->flag & ARM_B_BONES)
+                               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);
                        }
+                       
+                       glPopMatrix();
+               }
+       }
+       
+       /* if wire over solid, set offset */
+       index= -1;
+       if (dt>OB_WIRE) bglPolygonOffset(1.0);
+       else if(arm->flag & ARM_EDITMODE) index= 0;     // do selection codes
+       
+       for (eBone=G.edbo.first; eBone; eBone=eBone->next){
+               
+               glPushMatrix();
+               set_matrix_editbone(eBone);
+               
+               if(arm->flag & ARM_B_BONES)
+                       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, index, -1);
                }
+               if(arm->flag & ARM_DRAWAXES)
+                       drawaxes(0.25f);
                
-               /* restore */
-               if (dt>OB_WIRE) bglPolygonOffset(0.0);
+               glPopMatrix();
                
-               /* finally names */
-               if(arm->flag & ARM_DRAWNAMES) {
-                       // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
-                       if((G.f & G_PICKSEL) == 0) {
-                               float vec[3];
-                               
-                               if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
+               /* offset to parent */
+               if (eBone->parent) {
+                       BIF_ThemeColor(TH_WIRE);
+                       glLoadName (-1);
+                       setlinestyle(3);
+                       
+                       glBegin(GL_LINES);
+                       glVertex3fv(eBone->parent->tail);
+                       glVertex3fv(eBone->head);
+                       glEnd();
+                       
+                       setlinestyle(0);
+               }
+               if(index!=-1) index++;
+       }
+       
+       /* restore */
+       if (dt>OB_WIRE) bglPolygonOffset(0.0);
+       
+       /* finally names */
+       if(arm->flag & ARM_DRAWNAMES) {
+               // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
+               if((G.f & G_PICKSEL) == 0) {
+                       float vec[3];
+                       
+                       if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
+                       
+                       for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){
                                
-                               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_SELECTED) BIF_ThemeColor(TH_TEXT_HI);
+                               else BIF_ThemeColor(TH_TEXT);
                                
-                               if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
+                               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 */
+void draw_armature(Object *ob, int dt)
+{
+       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...
+       
+       /* editmode? */
+       if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) {
+               if(ob==G.obedit) arm->flag |= ARM_EDITMODE;
+               draw_ebones(ob, dt);
                arm->flag &= ~ARM_EDITMODE;
        }
        else{
index d825b551825999c1b1a65df22f104e038a296785..68dfd5732ccbb55c791e2a400391c7dc22ebe3a7 100644 (file)
@@ -1255,8 +1255,8 @@ static void draw_ipocurves(int sel)
                                                                        
                                                                        correct_bezpart(v1, v2, v3, v4);
                                                                        
-                                                                       maakbez(v1[0], v2[0], v3[0], v4[0], data, resol);
-                                                                       maakbez(v1[1], v2[1], v3[1], v4[1], data+1, resol);
+                                                                       forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, 3);
+                                                                       forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, 3);
                                                                        
                                                                        fp= data;
                                                                        while(resol--) {
index 8640f4b5c0a1d29a363f2a8fafa7c23f0054be43..709db81961bc4f0f8efd3a607add2b5b0d256495 100644 (file)
@@ -3737,6 +3737,7 @@ void draw_object(Base *base)
                drawlattice(ob);
                break;
        case OB_ARMATURE:
+               if(dt>OB_WIRE) set_gl_material(0);      // we use defmaterial
                draw_armature(ob, dt);
                break;
        default:
index 7aa49d91caba1bbcfbd7bfc955df5f07e6dfbe6c..36e208740c84e2794eff9cb0974295d262c78517 100644 (file)
@@ -156,7 +156,10 @@ static void make_boneList(ListBase* list, ListBase *bones, EditBone *parent)
                eBone->length= curBone->length;
                eBone->dist= curBone->dist;
                eBone->weight= curBone->weight;
+               eBone->xwidth= curBone->xwidth;
+               eBone->zwidth= curBone->zwidth;
                eBone->boneclass = curBone->boneclass;          
+               eBone->segments = curBone->segments;            
                
                BLI_addtail (list, eBone);
                
@@ -245,6 +248,10 @@ static void editbones_to_armature (ListBase *list, Object *ob)
                newBone->dist = eBone->dist;
                newBone->boneclass = eBone->boneclass;
                
+               newBone->xwidth = eBone->xwidth;
+               newBone->zwidth = eBone->zwidth;
+               newBone->segments= eBone->segments;
+               
        }
        
        /*      Fix parenting in a separate pass to ensure ebone->bone connections
@@ -1156,11 +1163,15 @@ static void add_bone_input (Object *ob)
                
                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;
+               bone->zwidth= 0.1;
                bone->boneclass = BONE_SKINNABLE;
+               bone->segments= 1;
                
                /*      Project cursor center to screenspace. */
                getmouseco_areawin(mval);
@@ -1503,11 +1514,15 @@ void extrude_armature(void)
                        VECCOPY (newbone->head, curbone->tail);
                        VECCOPY (newbone->tail, newbone->head);
                        newbone->parent = curbone;
+                       
                        newbone->flag = BONE_TIPSEL;
                        newbone->weight= curbone->weight;
                        newbone->dist= curbone->dist;
+                       newbone->xwidth= curbone->xwidth;
+                       newbone->zwidth= curbone->zwidth;
+                       newbone->segments= curbone->segments;
                        newbone->boneclass= curbone->boneclass;
-
+                       
                        /* See if there are any ik children of the parent */
                        for (partest = G.edbo.first; partest; partest=partest->next){
                                if ((partest->parent == curbone) && (partest->flag & BONE_IK_TOPARENT))
index 66f0543d460d02384e91829c24e04aa306d2933d..20e1b4c96aa43c5733ab08cb753903120c5c8a62 100644 (file)
@@ -1250,15 +1250,19 @@ void borderselect(void)
                                        if (val==LEFTMOUSE){
                                                if (index != -1){
                                                        bone = get_indexed_bone(G.obpose, index &~(BONESEL_TIP|BONESEL_ROOT));
-                                                       bone->flag |= BONE_SELECTED;
-                                                       select_actionchannel_by_name(G.obpose->action, bone->name, 1);
+                                                       if(bone) {
+                                                               bone->flag |= BONE_SELECTED;
+                                                               select_actionchannel_by_name(G.obpose->action, bone->name, 1);
+                                                       }
                                                }
                                        }
                                        else{   
                                                if (index != -1){
                                                        bone = get_indexed_bone(G.obpose, index &~(BONESEL_TIP|BONESEL_ROOT));
-                                                       bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED);
-                                                       select_actionchannel_by_name(G.obpose->action, bone->name, 0);
+                                                       if(bone) {
+                                                               bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED);
+                                                               select_actionchannel_by_name(G.obpose->action, bone->name, 0);
+                                                       }
                                                }
                                        }
                                }
index c7d0f62b2a16609ccc45468abf436efe0b7a8139..a841a85471827dcff3be4d42b97401295fd36e0e 100644 (file)
@@ -606,7 +606,7 @@ void BIF_InitTheme(void)
        btheme->tv3d.facedot_size= 4;
        
        SETCOL(btheme->tv3d.bone_solid, 200, 200, 200, 255);
-       SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 100);              // alpha 100 is not meant editable, used for wire+action draw
+       SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 80);               // alpha 80 is not meant editable, used for wire+action draw
        
        
        /* space buttons */
@@ -716,7 +716,7 @@ void BIF_InitTheme(void)
 
 char *BIF_ThemeColorsPup(int spacetype)
 {
-       char *cp= MEM_callocN(21*32, "theme pup");
+       char *cp= MEM_callocN(32*32, "theme pup");
        char str[32];
        
        if(spacetype==0) {
@@ -766,8 +766,8 @@ char *BIF_ThemeColorsPup(int spacetype)
                        sprintf(str, "Face Selected (transp) %%x%d|", TH_FACE_SELECT); strcat(cp, str);
                        sprintf(str, "Face Dot Selected %%x%d|", TH_FACE_DOT); strcat(cp, str);
                        sprintf(str, "Face Dot Size %%x%d|", TH_FACEDOT_SIZE); strcat(cp, str);
-                       sprintf(str, "Normal %%x%d", TH_NORMAL); strcat(cp, str);
-                       sprintf(str, "Bone Solid %%x%d", TH_BONE_SOLID); strcat(cp, str);
+                       sprintf(str, "Normal %%x%d|", TH_NORMAL); strcat(cp, str);
+                       sprintf(str, "Bone Solid %%x%d|", TH_BONE_SOLID); strcat(cp, str);
                        sprintf(str, "Bone Pose %%x%d", TH_BONE_POSE); strcat(cp, str);
                }
                else if(spacetype==SPACE_IPO) {
index 7300135c86fd0442496c12a389ecf8c59363eb07..6be450e6e220f6210af248b49d128a697bdde7a5 100644 (file)
@@ -1549,8 +1549,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                        doredraw= 1;
                                }
                                else if(G.obedit) {
+                                       
                                        if(G.qual==LR_ALTKEY) {
-                                               initTransform(TFM_SHRINKFATTEN, CTX_NONE);
+                                               if(G.obedit->type==OB_ARMATURE)
+                                                       initTransform(TFM_BONESIZE, CTX_NONE);
+                                               else
+                                                       initTransform(TFM_SHRINKFATTEN, CTX_NONE);
                                                Transform();
                                        }
                                        else if(G.qual==LR_CTRLKEY) {
index ab732f9eb1a7b4f4f10d5eaf120965ac9fb9c4a3..13945db60571ac4dd7a735c7b61a8a1b7d9897fb 100755 (executable)
@@ -497,6 +497,9 @@ void initTransform(int mode, int context) {
        case TFM_CREASE:
                initCrease(&Trans);
                break;
+       case TFM_BONESIZE:
+               initBoneSize(&Trans);
+               break;
        }
 
        initConstraint(&Trans);
@@ -2207,6 +2210,121 @@ void Mirror(short mode)
        scrarea_queue_headredraw(curarea);
 }
 
+/* ******************** EditBone 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);
+       
+       if (t->con.applySize) {
+               t->con.applySize(t, td, tmat);
+       }
+       
+       /* we've tucked the scale in loc */
+       oldy= td->iloc[1];
+       SizeToMat3(td->iloc, sizemat);
+       Mat3MulMat3(tmat, smat, sizemat);
+       Mat3ToSize(tmat, td->loc);
+       td->loc[1]= oldy;
+}
+
+
+int BoneSize(TransInfo *t, short mval[2]) 
+{
+       TransData *td = t->data;
+       float size[3], mat[3][3];
+       float ratio;
+       int i;
+       char str[50];
+       
+       /* for manipulator, center handle, the scaling can't be done relative to center */
+       if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) {
+               ratio = 1.0f - ((t->imval[0] - mval[0]) + (t->imval[1] - mval[1]))/100.0f;
+       }
+       else {
+               
+               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;
+               }
+               
+               /* flip scale, but not for manipulator center handle */
+               if      ((t->center2d[0] - mval[0]) * (t->center2d[0] - t->imval[0]) + 
+                        (t->center2d[1] - mval[1]) * (t->center2d[1] - t->imval[1]) < 0)
+                       ratio *= -1.0f;
+       }
+       
+       size[0] = size[1] = size[2] = ratio;
+       
+       snapGrid(t, size);
+       
+       if (hasNumInput(&t->num)) {
+               applyNumInput(&t->num, size);
+               constraintNumInput(t, size);
+       }
+       
+       SizeToMat3(size, mat);
+       
+       if (t->con.applySize) {
+               t->con.applySize(t, NULL, mat);
+       }
+       
+       Mat3CpyMat3(t->mat, mat);       // used in manipulator
+       
+       headerResize(t, size, str);
+       
+       for(i = 0 ; i < t->total; i++, td++) {
+               if (td->flag & TD_NOACTION)
+                       break;
+               
+               ElementBoneSize(t, td, mat);
+       }
+       
+       recalcData(t);
+       
+       headerprint(str);
+       
+       force_draw(0);
+       
+       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t->center);
+       
+       return 1;
+}
+
+void initBoneSize(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 = 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])
+                                                  ) );
+       
+       if(t->fac==0.0f) t->fac= 1.0f;  // prevent Inf
+}
+
+/* ************************************ */
 
 void BIF_TransformSetUndo(char *str)
 {
index 60adfa04ef46c5d5ff772a965e1bad838930befa..92e91d24b58fd9c691c15e428b42e001ed96cf6b 100755 (executable)
@@ -496,15 +496,19 @@ static void createTransArmatureVerts(TransInfo *t)
 {
        EditBone *ebo;
        TransData *td;
-       float mtx[3][3], smtx[3][3];
+       float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
 
        t->total = 0;
-       for (ebo=G.edbo.first;ebo;ebo=ebo->next){
-               if (ebo->flag & BONE_TIPSEL){
-                       t->total++;
+       for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
+               if (t->mode==TFM_BONESIZE) {
+                       if (ebo->flag & BONE_SELECTED)
+                               t->total++;
                }
-               if (ebo->flag & BONE_ROOTSEL){
-                       t->total++;
+               else {
+                       if (ebo->flag & BONE_TIPSEL)
+                               t->total++;
+                       if (ebo->flag & BONE_ROOTSEL)
+                               t->total++;
                }
        }
 
@@ -516,37 +520,62 @@ 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 (ebo->flag & BONE_TIPSEL){
-                       VECCOPY (td->iloc, ebo->tail);
-                       VECCOPY (td->center, td->iloc);
-                       td->loc= ebo->tail;
-                       td->flag= TD_SELECTED;
+               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);
+                               VECCOPY (td->center, ebo->head);
+                               td->flag= TD_SELECTED;
+                               
+                               /* use local bone matrix */
+                               VecSubf(delta, ebo->tail, ebo->head);   
+                               vec_roll_to_mat3(delta, ebo->roll, bonemat);
+                               Mat3MulMat3(td->mtx, mtx, bonemat);
+                               Mat3Inv(td->smtx, td->mtx);
+                               
+                               Mat3CpyMat3(td->axismtx, td->mtx);
+                               Mat3Ortho(td->axismtx);
 
-                       Mat3CpyMat3(td->smtx, smtx);
-                       Mat3CpyMat3(td->mtx, mtx);
+                               td->ext = NULL;
+                               td->tdi = NULL;
+                               td->val = NULL;
+                               
+                               td++;
+                       }
+               }
+               else {
+                       if (ebo->flag & BONE_TIPSEL){
+                               VECCOPY (td->iloc, ebo->tail);
+                               VECCOPY (td->center, td->iloc);
+                               td->loc= ebo->tail;
+                               td->flag= TD_SELECTED;
 
-                       td->ext = NULL;
-                       td->tdi = NULL;
-                       td->val = NULL;
+                               Mat3CpyMat3(td->smtx, smtx);
+                               Mat3CpyMat3(td->mtx, mtx);
 
-                       td++;
-               }
-               if (ebo->flag & BONE_ROOTSEL){
-                       VECCOPY (td->iloc, ebo->head);
-                       VECCOPY (td->center, td->iloc);
-                       td->loc= ebo->head;
-                       td->flag= TD_SELECTED;
+                               td->ext = NULL;
+                               td->tdi = NULL;
+                               td->val = NULL;
 
-                       Mat3CpyMat3(td->smtx, smtx);
-                       Mat3CpyMat3(td->mtx, mtx);
+                               td++;
+                       }
+                       if (ebo->flag & BONE_ROOTSEL){
+                               VECCOPY (td->iloc, ebo->head);
+                               VECCOPY (td->center, td->iloc);
+                               td->loc= ebo->head;
+                               td->flag= TD_SELECTED;
 
-                       td->ext = NULL;
-                       td->tdi = NULL;
-                       td->val = NULL;
+                               Mat3CpyMat3(td->smtx, smtx);
+                               Mat3CpyMat3(td->mtx, mtx);
 
-                       td++;
+                               td->ext = NULL;
+                               td->tdi = NULL;
+                               td->val = NULL;
+
+                               td++;
+                       }
                }
-                       
        }
 }
 
@@ -1600,6 +1629,12 @@ void createTransData(TransInfo *t)
                        }
                }
                t->flag |= T_EDIT;
+               
+               /* exception... hackish, we want bonescale to use bone orientation matrix (ton) */
+               if(t->mode==TFM_BONESIZE) {
+                       t->flag &= ~T_EDIT;
+                       t->flag |= T_POSE;
+               }
        }
        else {
                createTransObject(t);
index 3354560c07139bdf1c54502c239bbaa278b09656..1096bb364d8e3caf35cafb376b1d4bcafe177082 100644 (file)
@@ -232,7 +232,7 @@ static void init_userdef_file(void)
                        /* check for alpha==0 is safe, then color was never set */
                        if(btheme->tv3d.bone_solid[3]==0) {
                                SETCOL(btheme->tv3d.bone_solid, 200, 200, 200, 255);
-                               SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 100);
+                               SETCOL(btheme->tv3d.bone_pose, 80, 200, 255, 80);
                        }
                }
        }