From e67ba0ae330561424f18dbebaede835f81f45282 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sat, 16 Jul 2005 19:07:02 +0000 Subject: More armature goodies; 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. --- source/blender/blenkernel/BKE_armature.h | 9 +- source/blender/blenkernel/BKE_curve.h | 2 +- source/blender/blenkernel/intern/armature.c | 122 ++++++- source/blender/blenkernel/intern/curve.c | 11 +- source/blender/blenkernel/intern/displist.c | 8 +- source/blender/blenloader/intern/readfile.c | 1 + source/blender/include/BIF_editarmature.h | 6 +- source/blender/include/BIF_transform.h | 1 + source/blender/include/transform.h | 3 + source/blender/makesdna/DNA_action_types.h | 6 +- source/blender/makesdna/DNA_armature_types.h | 14 +- source/blender/src/buttons_editing.c | 106 +++++- source/blender/src/drawarmature.c | 495 ++++++++++++++++++++------- source/blender/src/drawipo.c | 4 +- source/blender/src/drawobject.c | 1 + source/blender/src/editarmature.c | 17 +- source/blender/src/editview.c | 12 +- source/blender/src/resources.c | 8 +- source/blender/src/space.c | 6 +- source/blender/src/transform.c | 118 +++++++ source/blender/src/transform_conversions.c | 95 +++-- source/blender/src/usiblender.c | 2 +- 22 files changed, 836 insertions(+), 211 deletions(-) diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 3b924b56c47..5b71c5a5917 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -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 } diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 7b76a438e59..709b7b1c811 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -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); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index bac11a3646d..7cd0e7d0f91 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -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]; asegments; 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 */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 98aa41b392e..7dd8c6efd65 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -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) { diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 874bec746f1..0532456c97b 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -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; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 25cab6cf8bb..42a9f49ee2e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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); } diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 056888e33f6..b0b6147f564 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -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; diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h index e8bdc8c2e30..57aaf37a65d 100755 --- a/source/blender/include/BIF_transform.h +++ b/source/blender/include/BIF_transform.h @@ -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 diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 69e9f1d919c..b776bd26c1a 100755 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -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); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index f88d298e5ee..4cb4f1dd1a2 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -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; diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 437a5c6a4e3..cfda7b60262 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; /* */ + 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 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index d5eca3c8a0a..65b634fe525 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -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(); diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index 4d474d65c9b..cd29a5ff21d 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -82,8 +82,96 @@ #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; amat); + 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{ diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index d825b551825..68dfd5732cc 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -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--) { diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 8640f4b5c0a..709db81961b 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -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: diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 7aa49d91cab..36e208740c8 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -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)) diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index 66f0543d460..20e1b4c96aa 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -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); + } } } } diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c index c7d0f62b2a1..a841a854718 100644 --- a/source/blender/src/resources.c +++ b/source/blender/src/resources.c @@ -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) { diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 7300135c86f..6be450e6e22 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -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) { diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index ab732f9eb1a..13945db6057 100755 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -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) { diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 60adfa04ef4..92e91d24b58 100755 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -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); diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 3354560c071..1096bb364d8 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -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); } } } -- cgit v1.2.3