diff options
author | Ton Roosendaal <ton@blender.org> | 2005-07-16 23:07:02 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2005-07-16 23:07:02 +0400 |
commit | e67ba0ae330561424f18dbebaede835f81f45282 (patch) | |
tree | 5c3726760a4afd50266e6a522fe7b42f4a4bb230 /source/blender/src | |
parent | 502c34ee4971bcc7cd4cb97090f84c9235518a9b (diff) |
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.
Diffstat (limited to 'source/blender/src')
-rw-r--r-- | source/blender/src/buttons_editing.c | 106 | ||||
-rw-r--r-- | source/blender/src/drawarmature.c | 495 | ||||
-rw-r--r-- | source/blender/src/drawipo.c | 4 | ||||
-rw-r--r-- | source/blender/src/drawobject.c | 1 | ||||
-rw-r--r-- | source/blender/src/editarmature.c | 17 | ||||
-rw-r--r-- | source/blender/src/editview.c | 12 | ||||
-rw-r--r-- | source/blender/src/resources.c | 8 | ||||
-rw-r--r-- | source/blender/src/space.c | 6 | ||||
-rwxr-xr-x | source/blender/src/transform.c | 118 | ||||
-rwxr-xr-x | source/blender/src/transform_conversions.c | 95 | ||||
-rw-r--r-- | source/blender/src/usiblender.c | 2 |
11 files changed, 678 insertions, 186 deletions
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; 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{ 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); } } } |