Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2005-07-16 23:07:02 +0400
committerTon Roosendaal <ton@blender.org>2005-07-16 23:07:02 +0400
commite67ba0ae330561424f18dbebaede835f81f45282 (patch)
tree5c3726760a4afd50266e6a522fe7b42f4a4bb230 /source
parent502c34ee4971bcc7cd4cb97090f84c9235518a9b (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')
-rw-r--r--source/blender/blenkernel/BKE_armature.h9
-rw-r--r--source/blender/blenkernel/BKE_curve.h2
-rw-r--r--source/blender/blenkernel/intern/armature.c122
-rw-r--r--source/blender/blenkernel/intern/curve.c11
-rw-r--r--source/blender/blenkernel/intern/displist.c8
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/include/BIF_editarmature.h6
-rwxr-xr-xsource/blender/include/BIF_transform.h1
-rwxr-xr-xsource/blender/include/transform.h3
-rw-r--r--source/blender/makesdna/DNA_action_types.h6
-rw-r--r--source/blender/makesdna/DNA_armature_types.h14
-rw-r--r--source/blender/src/buttons_editing.c106
-rw-r--r--source/blender/src/drawarmature.c495
-rw-r--r--source/blender/src/drawipo.c4
-rw-r--r--source/blender/src/drawobject.c1
-rw-r--r--source/blender/src/editarmature.c17
-rw-r--r--source/blender/src/editview.c12
-rw-r--r--source/blender/src/resources.c8
-rw-r--r--source/blender/src/space.c6
-rwxr-xr-xsource/blender/src/transform.c118
-rwxr-xr-xsource/blender/src/transform_conversions.c95
-rw-r--r--source/blender/src/usiblender.c2
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]; 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 */
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; 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);
}
}
}