Armature "Envelope" editing.

For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;

http://www.blender3d.org/cms/Armature_Envelopes.647.0.html

Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).

Also part of this commit is:

- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
  keep the PoseMode hidden Bones separate from EditMode.
  (In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
  mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
  data. Sounds logical, but remember that VertexGroups are partial on a
  Mesh, partial on Object. Weird design decision though...
  Anyhoo, at this moment the only way to have Bone Envelopes deform, is
  by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
  depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
  set.
This commit is contained in:
2005-08-19 12:35:15 +00:00
parent 92731af84f
commit 9e05d6efb5
23 changed files with 1237 additions and 351 deletions

View File

@@ -78,7 +78,7 @@ void init_armature_deform(struct Object *parent, struct Object *ob);
struct bArmature* get_armature (struct Object* ob);
struct Bone *get_named_bone (struct bArmature *arm, const char *name);
float dist_to_bone (float vec[3], float b1[3], float b2[3]);
float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, float rad2, float rdist);
void where_is_armature (struct bArmature *arm);
void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone);

View File

@@ -537,12 +537,13 @@ void init_armature_deform(Object *parent, Object *ob)
/* bone defmats are already in the channels, chan_mat */
}
float dist_to_bone (float vec[3], float b1[3], float b2[3])
/* using vec with dist to bone b1 - b2 */
float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, float rad2, float rdist)
{
/* float dist=0; */
float dist=0.0f;
float bdelta[3];
float pdelta[3];
float hsqr, a, l;
float hsqr, a, l, rad;
VecSubf (bdelta, b2, b1);
l = Normalise (bdelta);
@@ -553,40 +554,57 @@ float dist_to_bone (float vec[3], float b1[3], float b2[3])
hsqr = ((pdelta[0]*pdelta[0]) + (pdelta[1]*pdelta[1]) + (pdelta[2]*pdelta[2]));
if (a < 0.0F){
//return 100000;
/* If we're past the end of the bone, do some weird field attenuation thing */
return ((b1[0]-vec[0])*(b1[0]-vec[0]) +(b1[1]-vec[1])*(b1[1]-vec[1]) +(b1[2]-vec[2])*(b1[2]-vec[2])) ;
/* If we're past the end of the bone, do a spherical field attenuation thing */
dist= ((b1[0]-vec[0])*(b1[0]-vec[0]) +(b1[1]-vec[1])*(b1[1]-vec[1]) +(b1[2]-vec[2])*(b1[2]-vec[2])) ;
rad= rad1;
}
else if (a > l){
//return 100000;
/* If we're past the end of the bone, do some weird field attenuation thing */
return ((b2[0]-vec[0])*(b2[0]-vec[0]) +(b2[1]-vec[1])*(b2[1]-vec[1]) +(b2[2]-vec[2])*(b2[2]-vec[2])) ;
/* If we're past the end of the bone, do a spherical field attenuation thing */
dist= ((b2[0]-vec[0])*(b2[0]-vec[0]) +(b2[1]-vec[1])*(b2[1]-vec[1]) +(b2[2]-vec[2])*(b2[2]-vec[2])) ;
rad= rad2;
}
else {
return (hsqr - (a*a));
dist= (hsqr - (a*a));
if(l!=0.0f) {
rad= a/l;
rad= rad*rad2 + (1.0-rad)*rad1;
}
else rad= rad1;
}
a= rad*rad;
if(dist < a)
return 1.0f;
else {
l= rad+rdist;
l*= l;
if(rdist==0.0f || dist >= l)
return 0.0f;
else {
a= sqrt(dist)-rad;
return 1.0-( a*a )/( rdist*rdist );
}
}
}
static float dist_bone_deform(bPoseChannel *pchan, float *vec, float *co)
{
Bone *bone= pchan->bone;
float dist, fac, ifac;
float fac;
float cop[3];
float bdsqr, contrib=0.0;
float contrib=0.0;
if(bone==NULL) return 0.0f;
bdsqr = bone->dist*bone->dist;
VECCOPY (cop, co);
dist = dist_to_bone(cop, bone->arm_head, bone->arm_tail);
fac= distfactor_to_bone(cop, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
if ((dist) <= bdsqr){
fac = (dist)/bdsqr;
ifac = 1.0F-fac;
if (fac>0.0){
ifac*=bone->weight;
contrib= ifac;
fac*=bone->weight;
contrib= fac;
if(contrib>0.0) {
VECCOPY (cop, co);
@@ -594,7 +612,7 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, float *co)
Mat4MulVecfl(pchan->chan_mat, cop);
VecSubf (cop, cop, co); // Make this a delta from the base position
cop[0]*=ifac; cop[1]*=ifac; cop[2]*=ifac;
cop[0]*=fac; cop[1]*=fac; cop[2]*=fac;
VecAddf (vec, vec, cop);
}
}

View File

@@ -3373,6 +3373,22 @@ static int map_223_keybd_code_to_224_keybd_code(int code)
}
}
static void bone_version_238(ListBase *lb)
{
Bone *bone;
for(bone= lb->first; bone; bone= bone->next) {
if(bone->rad_tail==0.0f && bone->rad_head==0.0f) {
bone->rad_head= 0.25f*bone->length;
bone->rad_tail= 0.1f*bone->length;
bone->dist-= bone->rad_head;
if(bone->dist<=0.0f) bone->dist= 0.0f;
}
bone_version_238(&bone->childbase);
}
}
static void do_versions(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
@@ -4854,6 +4870,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if(main->versionfile <= 238) {
Lattice *lt;
Object *ob;
bArmature *arm;
for (lt=main->latt.first; lt; lt=lt->id.next) {
if (lt->fu==0.0 && lt->fv==0.0 && lt->fw==0.0) {
@@ -4880,6 +4897,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
ob->softflag &= ~OB_SB_ENABLE;
}
}
for(arm=main->armature.first; arm; arm= arm->id.next) {
bone_version_238(&arm->bonebase);
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */

View File

@@ -43,7 +43,7 @@ typedef struct EditBone
struct EditBone *parent;/* Editbones have a one-way link (i.e. children refer
to parents. This is converted to a two-way link for
normal bones when leaving editmode. */
void *temp; /* Used to store temporary data */
void *temp; /* Used to store temporary data */
char name[32];
float roll; /* Roll along axis. We'll ultimately use the axis/angle method
@@ -59,17 +59,14 @@ typedef struct EditBone
int flag;
int parNr; /* Used for retrieving values from the menu system */
/* Storage for transformation data used by the posing system.
Maybe a better solution would be to make bones a blenderObject
variant? Or perhaps to use a TOTALLY custom transformation scheme
for pose element, rather than trying to use the existing transObject
system?
*/
float dist, weight;
float xwidth, length, zwidth; /* put them in order! transform uses this as scale */
float ease1, ease2;
float rad_head, rad_tail;
short boneclass, segments;
float oldlength; /* for envelope scaling */
} EditBone;
@@ -127,6 +124,10 @@ void armature_bone_rename(struct bArmature *arm, char *oldname, char *newname);
void armature_flip_names(void);
EditBone *armature_bone_get_mirrored(EditBone *ebo);
void hide_selected_armature_bones(void);
void hide_unselected_armature_bones(void);
void show_all_armature_bones(void);
#define BONESEL_ROOT 0x10000000
#define BONESEL_TIP 0x20000000
#define BONESEL_BONE 0x40000000

View File

@@ -55,6 +55,8 @@ void free_posebuf(void);
void copy_posebuf (void);
void paste_posebuf (int flip);
void pose_adds_vgroups(struct Object *meshobj);
void pose_flip_names(void);
#endif

View File

@@ -51,6 +51,7 @@
#define TFM_CREASE 13
#define TFM_MIRROR 14
#define TFM_BONESIZE 15
#define TFM_BONE_ENVELOPE 16
/* TRANSFORM CONTEXTS */
#define CTX_NONE 0

View File

@@ -254,6 +254,9 @@ int Crease(TransInfo *t, short mval[2]);
void initBoneSize(TransInfo *t);
int BoneSize(TransInfo *t, short mval[2]);
void initBoneEnvelope(TransInfo *t);
int BoneEnvelope(TransInfo *t, short mval[2]);
/*********************** transform_conversions.c ********** */
struct ListBase;
void count_bone_select(TransInfo *t, struct ListBase *lb, int do_it);

View File

@@ -1,20 +1,12 @@
/* DNA_action_types.h May 2001
*
* support for the "action" datatype
*
* Reevan McKay
*
/*
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,9 +20,10 @@
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* Contributor(s): Original design: Reevan McKay
* Contributor(s): Full recode, Ton Roosendaal, Crete 2005
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
* ***** END GPL LICENSE BLOCK *****
*/

View File

@@ -49,7 +49,7 @@ typedef struct Bone {
ListBase childbase; /* Children */
char name[32]; /* Name of the bone - must be unique within the armature */
float roll, length; /* roll is input for editmode, length calculated */
float roll; /* roll is input for editmode, length calculated */
float head[3];
float tail[3]; /* head/tail and roll in Bone Space */
float bone_mat[3][3]; /* rotation derived from head/tail/roll */
@@ -60,9 +60,10 @@ typedef struct Bone {
float arm_tail[3]; /* head/tail and roll in Armature Space (rest pos) */
float arm_mat[4][4]; /* matrix: (bonemat(b)+head(b))*arm_mat(b-1), rest pos*/
float dist, weight; /* dist, weight: for non-deformgroup deforms */
float xwidth, zwidth; /* width: for block bones */
float ease1, ease2; /* length of bezier handles */
float dist, weight; /* dist, weight: for non-deformgroup deforms */
float xwidth, length, zwidth; /* width: for block bones. keep in this order, transform! */
float ease1, ease2; /* length of bezier handles */
float rad_head, rad_tail; /* radius for head/tail sphere, defining deform as well */
float size[3]; /* patch for upward compat, UNUSED! */
short boneclass;
@@ -99,6 +100,7 @@ typedef struct bArmature {
#define ARM_OCTA 0
#define ARM_LINE 1
#define ARM_B_BONE 2
#define ARM_ENVELOPE 3
/* bone->flag */
@@ -109,13 +111,16 @@ typedef struct bArmature {
#define BONE_TRANSFORM 8
#define BONE_IK_TOPARENT 16
/* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */
#define BONE_HIDDEN 64
/* hidden Bones when drawing Posechannels */
#define BONE_HIDDEN_P 64
/* For detecting cyclic dependancies */
#define BONE_DONE 128
/* active is on mouse clicks only */
#define BONE_ACTIVE 256
/* No parent rotation or scale */
#define BONE_HINGE 512
/* hidden Bones when drawing Armature Editmode */
#define BONE_HIDDEN_A 1024
/* bone->flag bits */
#define BONE_IK_TOPARENTBIT 4

View File

@@ -448,28 +448,28 @@ static void editing_panel_mesh_type(Object *ob, Mesh *me)
if(me->medge) val= 1.0; else val= 0.0;
uiDefBut(block, LABEL, 0, "Edges", 10,70,70,20, 0, val, 0, 0, 0, "");
if(me->medge==NULL) {
uiDefBut(block, BUT, B_MAKEEDGES, "Make", 80,70,84,19, 0, 0, 0, 0, 0, "Adds edges data to active Mesh object, enables creases/seams and faster wireframe draw");
uiDefBut(block, BUT, B_MAKEEDGES, "Make", 80,70,84,19, 0, 0, 0, 0, 0, "Adds edges data to active Mesh, enables creases/seams and faster wireframe draw");
}
else uiDefBut(block, BUT, B_DELEDGES, "Delete", 80,70,84,19, 0, 0, 0, 0, 0, "Deletes edges data from active Mesh object");
else uiDefBut(block, BUT, B_DELEDGES, "Delete", 80,70,84,19, 0, 0, 0, 0, 0, "Deletes edges data from active Mesh");
if(me->mcol) val= 1.0; else val= 0.0;
uiDefBut(block, LABEL, 0, "VertCol", 10,50,70,20, 0, val, 0, 0, 0, "");
if(me->mcol==NULL) {
uiDefBut(block, BUT, B_MAKEVERTCOL, "Make", 80,50,84,19, 0, 0, 0, 0, 0, "Enables vertex colour painting on active object");
uiDefBut(block, BUT, B_MAKEVERTCOL, "Make", 80,50,84,19, 0, 0, 0, 0, 0, "Enables vertex colour painting on active Mesh");
}
else uiDefBut(block, BUT, B_DELVERTCOL, "Delete", 80,50,84,19, 0, 0, 0, 0, 0, "Deletes vertex colours on active object");
else uiDefBut(block, BUT, B_DELVERTCOL, "Delete", 80,50,84,19, 0, 0, 0, 0, 0, "Deletes vertex colours on active Mesh");
if(me->tface) val= 1.0; else val= 0.0;
uiDefBut(block, LABEL, 0, "TexFace", 10,30,70,20, 0, val, 0, 0, 0, "");
if(me->tface==NULL) {
uiDefBut(block, BUT, B_MAKE_TFACES, "Make", 80,30,84,19, 0, 0, 0, 0, 0, "Enables the active object's faces for UV coordinate mapping");
uiDefBut(block, BUT, B_MAKE_TFACES, "Make", 80,30,84,19, 0, 0, 0, 0, 0, "Enables the active Mesh's faces for UV coordinate mapping");
}
else uiDefBut(block, BUT, B_DEL_TFACES, "Delete", 80,30,84,19, 0, 0, 0, 0, 0, "Deletes UV coordinates for active object's faces");
else uiDefBut(block, BUT, B_DEL_TFACES, "Delete", 80,30,84,19, 0, 0, 0, 0, 0, "Deletes UV coordinates for active Mesh's faces");
if(me->msticky) val= 1.0; else val= 0.0;
uiDefBut(block, LABEL, 0, "Sticky", 10,10,70,20, 0, val, 0, 0, 0, "");
if(me->msticky==NULL) {
uiDefBut(block, BUT, B_MAKESTICKY, "Make", 80,10,84,19, 0, 0, 0, 0, 0, "Creates Sticky coordinates for the active object from the current camera view background picture");
uiDefBut(block, BUT, B_MAKESTICKY, "Make", 80,10,84,19, 0, 0, 0, 0, 0, "Creates Sticky coordinates for the active Mesh from the current camera view background picture");
}
else uiDefBut(block, BUT, B_DELSTICKY, "Delete", 80,10,84,19, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates");
@@ -2217,9 +2217,10 @@ static void editing_panel_armature_type(Object *ob, bArmature *arm)
uiButSetFunc(but, armature_recalc_func, ob, NULL);
uiDefButBitI(block, TOG, ARM_DELAYDEFORM, REDRAWVIEW3D, "Delay Deform", 160, 180,150,20, &arm->flag, 0, 0, 0, 0, "Don't deform children when manipulating bones in pose mode");
uiBlockBeginAlign(block);
uiDefButI(block, ROW, REDRAWVIEW3D, "Octahedron", 10, 140,100,20, &arm->drawtype, 0, ARM_OCTA, 0, 0, "Draw bone as octahedra");
uiDefButI(block, ROW, REDRAWVIEW3D, "Sticks", 110, 140,100,20, &arm->drawtype, 0, ARM_LINE, 0, 0, "Draw bone as simple 2d lines with dots");
uiDefButI(block, ROW, REDRAWVIEW3D, "B-Bones", 210, 140,100,20, &arm->drawtype, 0, ARM_B_BONE, 0, 0, "Draw bone as boxes, showing subdivision and b-splines");
uiDefButI(block, ROW, REDRAWVIEW3D, "Octahedron", 10, 140,75,20, &arm->drawtype, 0, ARM_OCTA, 0, 0, "Draw bones as octahedra");
uiDefButI(block, ROW, REDRAWVIEW3D, "Stick", 85, 140,70,20, &arm->drawtype, 0, ARM_LINE, 0, 0, "Draw bones as simple 2d lines with dots");
uiDefButI(block, ROW, REDRAWVIEW3D, "B-Bone", 155, 140,70,20, &arm->drawtype, 0, ARM_B_BONE, 0, 0, "Draw bones as boxes, showing subdivision and b-splines");
uiDefButI(block, ROW, REDRAWVIEW3D, "Envelope", 225, 140,85,20, &arm->drawtype, 0, ARM_ENVELOPE, 0, 0, "Draw bones as extruded spheres, showing deformation influence volume");
uiBlockBeginAlign(block);
uiDefButBitI(block, TOG, ARM_DRAWAXES, REDRAWVIEW3D, "Draw Axes", 10, 110,100,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes");
@@ -2286,7 +2287,7 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm)
uiDefButBitI(block, TOG, BONE_HINGE, REDRAWVIEW3D, "Hinge", bx-10,by-38,117,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
uiDefButBitS(block, TOGN, 1,REDRAWVIEW3D, "Skinnable", bx+110, by-38, 105, 18, &curBone->boneclass, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone is included in automatic creation of vertex groups");
/* Hide in posemode flag */
uiDefButBitI(block, TOG, BONE_HIDDEN, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode");
uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
uiBlockEndAlign(block);
by-=60;
@@ -2346,7 +2347,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
uiButSetFunc(but, armature_recalc_func, ob, NULL);
uiDefButBitS(block, TOGN, 1,REDRAWVIEW3D, "Skinnable", bx+110, by-38, 105, 18, &curBone->boneclass, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone is included in automatic creation of vertex groups");
/* Hide in posemode flag */
uiDefButBitI(block, TOG, BONE_HIDDEN, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode");
uiDefButBitI(block, TOG, BONE_HIDDEN_P, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode");
uiBlockEndAlign(block);
by-=60;

View File

@@ -372,6 +372,388 @@ static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id)
}
/* 16 values of sin function (still same result!) */
static float si[16] = {
0.00000000,
0.20129852, 0.39435585,
0.57126821, 0.72479278,
0.84864425, 0.93775213,
0.98846832, 0.99871650,
0.96807711, 0.89780453,
0.79077573, 0.65137248,
0.48530196, 0.29936312,
0.10116832
};
/* 16 values of cos function (still same result!) */
static float co[16] ={
1.00000000,
0.97952994, 0.91895781,
0.82076344, 0.68896691,
0.52896401, 0.34730525,
0.15142777, -0.05064916,
-0.25065253, -0.44039415,
-0.61210598, -0.75875812,
-0.87434661, -0.95413925,
-0.99486932
};
/* smat, imat = mat & imat to draw screenaligned */
static void draw_sphere_bone_dist(float smat[][4], float imat[][4], int boneflag, bPoseChannel *pchan, EditBone *ebone)
{
float head, tail, length, dist;
float *headvec, *tailvec, dirvec[3];
/* figure out the sizes of spheres */
if(ebone) {
/* this routine doesn't call set_matrix_editbone() that calculates it */
ebone->length = VecLenf(ebone->head, ebone->tail);
length= ebone->length;
tail= ebone->rad_tail;
dist= ebone->dist;
if (ebone->parent && (ebone->flag & BONE_IK_TOPARENT))
head= ebone->parent->rad_tail;
else
head= ebone->rad_head;
headvec= ebone->head;
tailvec= ebone->tail;
}
else {
length= pchan->bone->length;
tail= pchan->bone->rad_tail;
dist= pchan->bone->dist;
if (pchan->parent && (pchan->bone->flag & BONE_IK_TOPARENT))
head= pchan->parent->bone->rad_tail;
else
head= pchan->bone->rad_head;
headvec= pchan->pose_head;
tailvec= pchan->pose_tail;
}
/* ***** draw it ***** */
/* move vector to viewspace */
VecSubf(dirvec, tailvec, headvec);
Mat4Mul3Vecfl(smat, dirvec);
/* clear zcomp */
dirvec[2]= 0.0;
/* move vector back */
Mat4Mul3Vecfl(imat, dirvec);
if(0.0f != Normalise(dirvec)) {
float norvec[3], vec1[3], vec2[3], vec[3];
int a;
//VecMulf(dirvec, head);
Crossf(norvec, dirvec, imat[2]);
glBegin(GL_QUAD_STRIP);
for(a=0; a<16; a++) {
vec[0]= - *(si+a) * dirvec[0] + *(co+a) * norvec[0];
vec[1]= - *(si+a) * dirvec[1] + *(co+a) * norvec[1];
vec[2]= - *(si+a) * dirvec[2] + *(co+a) * norvec[2];
vec1[0]= headvec[0] + head*vec[0];
vec1[1]= headvec[1] + head*vec[1];
vec1[2]= headvec[2] + head*vec[2];
vec2[0]= headvec[0] + (head+dist)*vec[0];
vec2[1]= headvec[1] + (head+dist)*vec[1];
vec2[2]= headvec[2] + (head+dist)*vec[2];
glColor4ub(255, 255, 255, 50);
glVertex3fv(vec1);
//glColor4ub(255, 255, 255, 0);
glVertex3fv(vec2);
}
for(a=15; a>=0; a--) {
vec[0]= *(si+a) * dirvec[0] + *(co+a) * norvec[0];
vec[1]= *(si+a) * dirvec[1] + *(co+a) * norvec[1];
vec[2]= *(si+a) * dirvec[2] + *(co+a) * norvec[2];
vec1[0]= tailvec[0] + tail*vec[0];
vec1[1]= tailvec[1] + tail*vec[1];
vec1[2]= tailvec[2] + tail*vec[2];
vec2[0]= tailvec[0] + (tail+dist)*vec[0];
vec2[1]= tailvec[1] + (tail+dist)*vec[1];
vec2[2]= tailvec[2] + (tail+dist)*vec[2];
//glColor4ub(255, 255, 255, 50);
glVertex3fv(vec1);
//glColor4ub(255, 255, 255, 0);
glVertex3fv(vec2);
}
/* make it cyclic... */
vec[0]= - *(si) * dirvec[0] + *(co) * norvec[0];
vec[1]= - *(si) * dirvec[1] + *(co) * norvec[1];
vec[2]= - *(si) * dirvec[2] + *(co) * norvec[2];
vec1[0]= headvec[0] + head*vec[0];
vec1[1]= headvec[1] + head*vec[1];
vec1[2]= headvec[2] + head*vec[2];
vec2[0]= headvec[0] + (head+dist)*vec[0];
vec2[1]= headvec[1] + (head+dist)*vec[1];
vec2[2]= headvec[2] + (head+dist)*vec[2];
//glColor4ub(255, 255, 255, 50);
glVertex3fv(vec1);
//glColor4ub(255, 255, 255, 0);
glVertex3fv(vec2);
glEnd();
}
}
/* smat, imat = mat & imat to draw screenaligned */
static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
{
float head, tail, length;
float *headvec, *tailvec, dirvec[3];
/* figure out the sizes of spheres */
if(ebone) {
/* this routine doesn't call set_matrix_editbone() that calculates it */
ebone->length = VecLenf(ebone->head, ebone->tail);
length= ebone->length;
tail= ebone->rad_tail;
if (ebone->parent && (boneflag & BONE_IK_TOPARENT))
head= ebone->parent->rad_tail;
else
head= ebone->rad_head;
headvec= ebone->head;
tailvec= ebone->tail;
}
else {
length= pchan->bone->length;
tail= pchan->bone->rad_tail;
if (pchan->parent && (boneflag & BONE_IK_TOPARENT))
head= pchan->parent->bone->rad_tail;
else
head= pchan->bone->rad_head;
headvec= pchan->pose_head;
tailvec= pchan->pose_tail;
}
/* sphere root color */
if(armflag & ARM_EDITMODE) {
if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
else BIF_ThemeColor(TH_VERTEX);
}
else if(armflag & ARM_POSEMODE) {
/* in black or selection color */
if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
else BIF_ThemeColor(TH_WIRE);
}
/* Draw root point if we have no IK parent */
if (!(boneflag & BONE_IK_TOPARENT)){
if (id != -1)
glLoadName (id | BONESEL_ROOT);
drawcircball(GL_LINE_LOOP, headvec, head, imat);
}
/* Draw tip point */
if(armflag & ARM_EDITMODE) {
if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
else BIF_ThemeColor(TH_VERTEX);
}
if (id != -1)
glLoadName (id | BONESEL_TIP);
drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
/* base */
if(armflag & ARM_EDITMODE) {
if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_SELECT);
else BIF_ThemeColor(TH_WIRE);
}
VecSubf(dirvec, tailvec, headvec);
/* move vector to viewspace */
Mat4Mul3Vecfl(smat, dirvec);
/* clear zcomp */
dirvec[2]= 0.0;
/* move vector back */
Mat4Mul3Vecfl(imat, dirvec);
if(0.0f != Normalise(dirvec)) {
float norvech[3], norvect[3], vec[3];
VECCOPY(vec, dirvec);
VecMulf(dirvec, head);
Crossf(norvech, dirvec, imat[2]);
VecMulf(vec, tail);
Crossf(norvect, vec, imat[2]);
if (id != -1)
glLoadName (id | BONESEL_BONE);
glBegin(GL_LINES);
vec[0]= headvec[0] + norvech[0];
vec[1]= headvec[1] + norvech[1];
vec[2]= headvec[2] + norvech[2];
glVertex3fv(vec);
vec[0]= tailvec[0] + norvect[0];
vec[1]= tailvec[1] + norvect[1];
vec[2]= tailvec[2] + norvect[2];
glVertex3fv(vec);
vec[0]= headvec[0] - norvech[0];
vec[1]= headvec[1] - norvech[1];
vec[2]= headvec[2] - norvech[2];
glVertex3fv(vec);
vec[0]= tailvec[0] - norvect[0];
vec[1]= tailvec[1] - norvect[1];
vec[2]= tailvec[2] - norvect[2];
glVertex3fv(vec);
glEnd();
}
}
/* does wire only for outline selecting */
static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
{
GLUquadricObj *qobj;
float head, tail, length;
float fac1, fac2;
glPushMatrix();
qobj = gluNewQuadric();
/* figure out the sizes of spheres */
if(ebone) {
length= ebone->length;
tail= ebone->rad_tail;
if (ebone->parent && (boneflag & BONE_IK_TOPARENT))
head= ebone->parent->rad_tail;
else
head= ebone->rad_head;
}
else {
length= pchan->bone->length;
tail= pchan->bone->rad_tail;
if (pchan->parent && (boneflag & BONE_IK_TOPARENT))
head= pchan->parent->bone->rad_tail;
else
head= pchan->bone->rad_head;
}
/* move to z-axis space */
glRotatef (-90.0f, 1.0f, 0.0f, 0.0f);
if(dt==OB_SOLID) {
/* set up solid drawing */
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
gluQuadricDrawStyle(qobj, GLU_FILL);
glShadeModel(GL_SMOOTH);
}
else {
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
}
/* sphere root color */
if(armflag & ARM_EDITMODE) {
if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
else BIF_ThemeColorShade(TH_BONE_SOLID, -30);
}
else if(armflag & ARM_POSEMODE) {
if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 10);
else if (boneflag & BONE_SELECTED) BIF_ThemeColorShade(TH_BONE_POSE, -30);
else BIF_ThemeColorShade(TH_BONE_SOLID, -30);
}
else if(dt==OB_SOLID)
BIF_ThemeColorShade(TH_BONE_SOLID, -30);
/* Draw root point if we have no IK parent */
if (!(boneflag & BONE_IK_TOPARENT)){
if (id != -1)
glLoadName (id | BONESEL_ROOT);
gluSphere( qobj, head, 16, 10);
}
/* Draw tip point */
if(armflag & ARM_EDITMODE) {
if (boneflag & BONE_TIPSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
else BIF_ThemeColorShade(TH_BONE_SOLID, -30);
}
if (id != -1)
glLoadName (id | BONESEL_TIP);
glTranslatef(0.0, 0.0, length);
gluSphere( qobj, tail, 16, 10);
glTranslatef(0.0, 0.0, -length);
/* base */
if(armflag & ARM_EDITMODE) {
if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_SELECT);
else BIF_ThemeColor(TH_BONE_SOLID);
}
else if(armflag & ARM_POSEMODE) {
if (boneflag & BONE_ACTIVE) BIF_ThemeColorShade(TH_BONE_POSE, 40);
else if (boneflag & BONE_SELECTED) BIF_ThemeColor(TH_BONE_POSE);
else BIF_ThemeColor(TH_BONE_SOLID);
}
else if(dt==OB_SOLID)
BIF_ThemeColor(TH_BONE_SOLID);
fac1= (length-head)/length;
fac2= (length-tail)/length;
if(length > head+tail) {
if (id != -1)
glLoadName (id | BONESEL_BONE);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0, -1.0);
glTranslatef(0.0f, 0.0f, head);
gluCylinder(qobj, fac1*head + (1.0f-fac1)*tail, fac2*tail + (1.0f-fac2)*head, length-head-tail, 16, 1);
glTranslatef(0.0f, 0.0f, -head);
glDisable(GL_POLYGON_OFFSET_FILL);
/* draw sphere on extrema */
glTranslatef(0.0f, 0.0f, length-tail);
gluSphere( qobj, fac2*tail + (1.0f-fac2)*head, 16, 10);
glTranslatef(0.0f, 0.0f, -length+tail);
glTranslatef(0.0f, 0.0f, head);
gluSphere( qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
}
else {
/* 1 sphere in center */
glTranslatef(0.0f, 0.0f, (head + length-tail)/2.0);
gluSphere( qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
}
/* restore */
if(dt==OB_SOLID) {
glShadeModel(GL_FLAT);
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
}
glPopMatrix();
gluDeleteQuadric(qobj);
}
static char bm_dot6[]= {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0};
static char bm_dot8[]= {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C};
@@ -606,12 +988,14 @@ static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsign
}
}
static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id)
static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, float length)
{
/* Draw a 3d octahedral bone, we use normalized space based on length,
for glDisplayLists */
glScalef(length, length, length);
/* set up solid drawing */
if(dt > OB_WIRE) {
glEnable(GL_COLOR_MATERIAL);
@@ -688,40 +1072,69 @@ static void draw_pose_channels(Base *base, int dt)
bPoseChannel *pchan;
Bone *bone;
GLfloat tmp;
float smat[4][4], imat[4][4];
int index= -1;
int do_dashed= 1;
short flag, constflag;
/* little speedup, also make sure transparent only draws once */
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
/* hacky... prevent outline select from drawing dashed helplines */
glGetFloatv(GL_LINE_WIDTH, &tmp);
if(tmp > 1.1) do_dashed= 0;
/* precalc inverse matrix for drawing screen aligned */
if(arm->drawtype==ARM_ENVELOPE) {
/* precalc inverse matrix for drawing screen aligned */
mygetmatrix(smat);
Mat4MulFloat3(smat[0], 1.0f/VecLength(ob->obmat[0]));
Mat4Invert(imat, smat);
/* and draw blended distances */
if(arm->flag & ARM_POSEMODE) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
//glShadeModel(GL_SMOOTH);
if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
bone= pchan->bone;
if(bone && !(bone->flag & BONE_HIDDEN_P)) {
if(bone->flag & (BONE_SELECTED))
draw_sphere_bone_dist(smat, imat, bone->flag, pchan, NULL);
}
}
if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
//glShadeModel(GL_FLAT);
}
}
/* little speedup, also make sure transparent only draws once */
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
/* if solid we draw that first, with selection codes, but without names, axes etc */
if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) {
if(arm->flag & ARM_POSEMODE) index= base->selcol;
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
bone= pchan->bone;
if(bone && !(bone->flag & BONE_HIDDEN)) {
if(bone && !(bone->flag & BONE_HIDDEN_P)) {
glPushMatrix();
glMultMatrixf(pchan->pose_mat);
/* catch exception for bone with hidden parent */
flag= bone->flag;
if(bone->parent && (bone->parent->flag & BONE_HIDDEN))
if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P))
flag &= ~BONE_IK_TOPARENT;
if(arm->drawtype==ARM_B_BONE)
if(arm->drawtype==ARM_ENVELOPE)
draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
else if(arm->drawtype==ARM_B_BONE)
draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
else {
/* scale the matrix to unit bone space */
glScalef(bone->length, bone->length, bone->length);
draw_bone(OB_SOLID, arm->flag, flag, 0, index);
draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->length);
}
glPopMatrix();
}
@@ -747,7 +1160,7 @@ static void draw_pose_channels(Base *base, int dt)
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
bone= pchan->bone;
if(bone && !(bone->flag & BONE_HIDDEN)) {
if(bone && !(bone->flag & BONE_HIDDEN_P)) {
// Draw a line from our root to the parent's tip
if (do_dashed && bone->parent && !(bone->flag & BONE_IK_TOPARENT) ){
@@ -763,12 +1176,14 @@ static void draw_pose_channels(Base *base, int dt)
setlinestyle(0);
}
glPushMatrix();
glMultMatrixf(pchan->pose_mat);
if(arm->drawtype!=ARM_ENVELOPE) {
glPushMatrix();
glMultMatrixf(pchan->pose_mat);
}
/* catch exception for bone with hidden parent */
flag= bone->flag;
if(bone->parent && (bone->parent->flag & BONE_HIDDEN))
if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P))
flag &= ~BONE_IK_TOPARENT;
/* extra draw service for pose mode */
@@ -776,18 +1191,20 @@ static void draw_pose_channels(Base *base, int dt)
if(pchan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE))
constflag |= PCHAN_HAS_ACTION;
if(arm->drawtype==ARM_LINE)
if(arm->drawtype==ARM_ENVELOPE) {
if(dt<OB_SOLID)
draw_sphere_bone_wire(smat, imat, arm->flag, flag, constflag, index, pchan, NULL);
}
else if(arm->drawtype==ARM_LINE)
draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
else if(arm->drawtype==ARM_B_BONE)
draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
else {
/* scale the matrix to unit bone space */
glScalef(bone->length, bone->length, bone->length);
draw_bone(OB_WIRE, arm->flag, flag, constflag, index);
draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
}
glPopMatrix();
if(arm->drawtype!=ARM_ENVELOPE)
glPopMatrix();
}
if (index!= -1) index+= 0x10000; // pose bones count in higher 2 bytes only
}
@@ -864,24 +1281,58 @@ static void draw_ebones(Object *ob, int dt)
{
EditBone *eBone;
bArmature *arm= ob->data;
float smat[4][4], imat[4][4];
unsigned int index;
int flag;
/* envelope (deform distance) */
if(arm->drawtype==ARM_ENVELOPE) {
/* precalc inverse matrix for drawing screen aligned */
mygetmatrix(smat);
Mat4MulFloat3(smat[0], 1.0f/VecLength(ob->obmat[0]));
Mat4Invert(imat, smat);
/* and draw blended distances */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
//glShadeModel(GL_SMOOTH);
if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){
if(!(eBone->flag & BONE_HIDDEN_A))
if(eBone->flag & (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL))
draw_sphere_bone_dist(smat, imat, eBone->flag, NULL, eBone);
}
if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
//glShadeModel(GL_FLAT);
}
/* if solid we draw it first */
if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) {
index= 0;
for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){
glPushMatrix();
set_matrix_editbone(eBone);
if(!(eBone->flag & BONE_HIDDEN_A)) {
glPushMatrix();
set_matrix_editbone(eBone);
if(arm->drawtype==ARM_B_BONE)
draw_b_bone(OB_SOLID, arm->flag, eBone->flag, 0, index, NULL, eBone);
else {
/* scale the matrix to unit bone space */
glScalef(eBone->length, eBone->length, eBone->length);
draw_bone(OB_SOLID, arm->flag, eBone->flag, 0, index);
/* catch exception for bone with hidden parent */
flag= eBone->flag;
if(eBone->parent && (eBone->parent->flag & BONE_HIDDEN_A))
flag &= ~BONE_IK_TOPARENT;
if(arm->drawtype==ARM_ENVELOPE)
draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
else if(arm->drawtype==ARM_B_BONE)
draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
else {
draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
}
glPopMatrix();
}
glPopMatrix();
}
}
@@ -897,36 +1348,47 @@ static void draw_ebones(Object *ob, int dt)
index= 0; // do selection codes
for (eBone=G.edbo.first; eBone; eBone=eBone->next){
if(!(eBone->flag & BONE_HIDDEN_A)) {
glPushMatrix();
set_matrix_editbone(eBone);
/* catch exception for bone with hidden parent */
flag= eBone->flag;
if(eBone->parent && (eBone->parent->flag & BONE_HIDDEN_A))
flag &= ~BONE_IK_TOPARENT;
if(arm->drawtype==ARM_LINE)
draw_line_bone(arm->flag, eBone->flag, 0, index, NULL, eBone);
else if(arm->drawtype==ARM_B_BONE)
draw_b_bone(OB_WIRE, arm->flag, eBone->flag, 0, index, NULL, eBone);
else {
/* scale the matrix to unit bone space */
glScalef(eBone->length, eBone->length, eBone->length);
draw_bone(OB_WIRE, arm->flag, eBone->flag, 0, index);
}
if(arm->flag & ARM_DRAWAXES)
drawaxes(0.25f);
if(arm->drawtype==ARM_ENVELOPE) {
if(dt<OB_SOLID)
draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
}
else {
glPushMatrix();
set_matrix_editbone(eBone);
glPopMatrix();
if(arm->drawtype==ARM_LINE)
draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
else if(arm->drawtype==ARM_B_BONE)
draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
else
draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
/* offset to parent */
if (eBone->parent) {
BIF_ThemeColor(TH_WIRE);
glLoadName (-1); // -1 here is OK!
setlinestyle(3);
if(arm->flag & ARM_DRAWAXES)
drawaxes(0.25f);
glBegin(GL_LINES);
glVertex3fv(eBone->parent->tail);
glVertex3fv(eBone->head);
glEnd();
glPopMatrix();
}
setlinestyle(0);
/* offset to parent */
if (eBone->parent) {
BIF_ThemeColor(TH_WIRE);
glLoadName (-1); // -1 here is OK!
setlinestyle(3);
glBegin(GL_LINES);
glVertex3fv(eBone->parent->tail);
glVertex3fv(eBone->head);
glEnd();
setlinestyle(0);
}
}
if(index!=-1) index++;
}
@@ -944,20 +1406,21 @@ static void draw_ebones(Object *ob, int dt)
if(G.vd->zbuf) glDisable(GL_DEPTH_TEST);
for (eBone=G.edbo.first, index=0; eBone; eBone=eBone->next, index++){
if(!(eBone->flag & BONE_HIDDEN_A)) {
if(eBone->flag & BONE_SELECTED) BIF_ThemeColor(TH_TEXT_HI);
else BIF_ThemeColor(TH_TEXT);
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);
VecMidf(vec, eBone->head, eBone->tail);
glRasterPos3fv(vec);
BMF_DrawString(G.font, " ");
BMF_DrawString(G.font, eBone->name);
}
}
if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
}
}
}
/* called from drawobject.c */
@@ -966,9 +1429,16 @@ void draw_armature(Base *base, int dt)
Object *ob= base->object;
bArmature *arm= ob->data;
/* we use color for solid lighting */
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // only for lighting...
if(dt>OB_WIRE) {
/* we use color for solid lighting */
glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
glEnable(GL_COLOR_MATERIAL);
glColor3ub(0,0,0); // clear spec
glDisable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // only for lighting...
}
/* arm->flag is being used to detect mode... */
/* editmode? */

View File

@@ -163,6 +163,8 @@ static void make_boneList(ListBase* list, ListBase *bones, EditBone *parent)
eBone->zwidth= curBone->zwidth;
eBone->ease1= curBone->ease1;
eBone->ease2= curBone->ease2;
eBone->rad_head= curBone->rad_head;
eBone->rad_tail= curBone->rad_tail;
eBone->segments = curBone->segments;
eBone->boneclass = curBone->boneclass;
@@ -256,6 +258,8 @@ static void editbones_to_armature (ListBase *list, Object *ob)
newBone->zwidth = eBone->zwidth;
newBone->ease1= eBone->ease1;
newBone->ease2= eBone->ease2;
newBone->rad_head= eBone->rad_head;
newBone->rad_tail= eBone->rad_tail;
newBone->segments= eBone->segments;
newBone->boneclass = eBone->boneclass;
@@ -1162,11 +1166,11 @@ static EditBone *add_editbone(void)
{
EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
BLI_addtail(&G.edbo, bone);
strcpy (bone->name,"Bone");
unique_editbone_name (bone->name);
BLI_addtail(&G.edbo, bone);
bone->flag |= BONE_TIPSEL;
bone->weight= 1.0F;
bone->dist= 1.0F;
@@ -1174,6 +1178,8 @@ static EditBone *add_editbone(void)
bone->zwidth= 0.1;
bone->ease1= 1.0;
bone->ease2= 1.0;
bone->rad_head= 0.25;
bone->rad_tail= 0.1;
bone->segments= 1;
bone->boneclass = BONE_SKINNABLE;
@@ -1381,6 +1387,55 @@ void adduplicate_armature(void)
/* *************** END Adding stuff in editmode *************** */
/* *************** Tools in editmode *********** */
void hide_selected_armature_bones(void)
{
EditBone *ebone;
for (ebone = G.edbo.first; ebone; ebone=ebone->next){
if(ebone->flag & (BONE_SELECTED)) {
ebone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
ebone->flag |= BONE_HIDDEN_A;
}
}
countall();
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
}
void hide_unselected_armature_bones(void)
{
EditBone *ebone;
for (ebone = G.edbo.first; ebone; ebone=ebone->next){
if(ebone->flag & (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL));
else {
ebone->flag &= ~BONE_ACTIVE;
ebone->flag |= BONE_HIDDEN_A;
}
}
countall();
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
}
void show_all_armature_bones(void)
{
EditBone *ebone;
for (ebone = G.edbo.first; ebone; ebone=ebone->next){
if(ebone->flag & BONE_HIDDEN_A) {
ebone->flag |= (BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
ebone->flag &= ~BONE_HIDDEN_A;
}
}
countall();
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
}
/* the "IK" button in editbuttons */
void attach_bone_to_parent_cb(void *bonev, void *arg2_unused)
{
@@ -1558,13 +1613,34 @@ void extrude_armature(int forked)
{
bArmature *arm= G.obedit->data;
EditBone *newbone, *ebone, *flipbone, *first=NULL, *partest;
int a, totbone= 0;
int a, totbone= 0, do_extrude;
TEST_EDITARMATURE;
/* since we allow root extrude too, we have to make sure selection is OK */
for (ebone = G.edbo.first; ebone; ebone=ebone->next){
if(ebone->flag & BONE_ROOTSEL) {
if(ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) {
if(ebone->parent->flag & BONE_TIPSEL)
ebone->flag &= ~BONE_ROOTSEL;
}
}
}
/* Duplicate the necessary bones */
for (ebone = G.edbo.first; ((ebone) && (ebone!=first)); ebone=ebone->next){
if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED)) {
/* we extrude per definition the tip */
do_extrude= 0;
if (ebone->flag & (BONE_TIPSEL|BONE_SELECTED))
do_extrude= 1;
else if(ebone->flag & BONE_ROOTSEL) {
/* but, a bone with parent deselected we do the root... */
if(ebone->parent && (ebone->parent->flag & BONE_TIPSEL));
else do_extrude= 2;
}
if (do_extrude) {
/* we re-use code for mirror editing... */
flipbone= NULL;
@@ -1572,7 +1648,7 @@ void extrude_armature(int forked)
flipbone= armature_bone_get_mirrored(ebone);
if (flipbone) {
forked= 0; // we extrude 2 different bones
if(flipbone->flag & (BONE_TIPSEL|BONE_SELECTED))
if(flipbone->flag & (BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED))
/* don't want this bone to be selected... */
flipbone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
}
@@ -1592,28 +1668,42 @@ void extrude_armature(int forked)
totbone++;
newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
VECCOPY (newbone->head, ebone->tail);
VECCOPY (newbone->tail, newbone->head);
newbone->parent = ebone;
if(do_extrude==1) {
VECCOPY (newbone->head, ebone->tail);
VECCOPY (newbone->tail, newbone->head);
newbone->parent = ebone;
newbone->flag = ebone->flag & BONE_TIPSEL; // copies it, in case mirrored bone
}
else {
VECCOPY(newbone->head, ebone->head);
VECCOPY(newbone->tail, ebone->head);
newbone->parent= ebone->parent;
newbone->flag= BONE_TIPSEL;
}
newbone->flag = ebone->flag & BONE_TIPSEL; // copies it, in case mirrored bone
newbone->weight= ebone->weight;
newbone->dist= ebone->dist;
newbone->xwidth= ebone->xwidth;
newbone->zwidth= ebone->zwidth;
newbone->ease1= ebone->ease1;
newbone->ease2= ebone->ease2;
newbone->segments= ebone->segments;
newbone->rad_head= ebone->rad_tail; // dont copy entire bone...
newbone->rad_tail= ebone->rad_tail;
newbone->segments= 1;
newbone->boneclass= ebone->boneclass;
/* See if there are any ik children of the parent */
for (partest = G.edbo.first; partest; partest=partest->next){
if ((partest->parent == ebone) && (partest->flag & BONE_IK_TOPARENT))
break;
}
if(do_extrude==1) {
for (partest = G.edbo.first; partest; partest=partest->next){
if ((partest->parent == ebone) && (partest->flag & BONE_IK_TOPARENT))
break;
}
if (!partest)
newbone->flag |= BONE_IK_TOPARENT;
if (!partest)
newbone->flag |= BONE_IK_TOPARENT;
}
strcpy (newbone->name, ebone->name);
@@ -1771,7 +1861,7 @@ static void deselect_bonechildren (Object *ob, Bone *bone, int mode)
if (mode==0)
bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
else if (mode==1) {
if(!(bone->flag & BONE_HIDDEN))
if(!(bone->flag & BONE_HIDDEN_P))
bone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
}
else bone->flag &= ~BONE_ACTIVE;
@@ -2000,12 +2090,15 @@ static void add_verts_to_closest_dgroup(Object *ob, Object *par)
* on the subsurf limit surface is used to generate
* the weights rather than the verts on the cage
* mesh.
*
* ("Limit surface" = same amount of vertices as mesh, but vertices
* moved to the subsurfed position, like for 'optimal').
*/
bArmature *arm;
Bone **bonelist, **bonehandle, *bone;
bDeformGroup **dgrouplist, **dgrouphandle, *defgroup;
float *distance, mindist = 0.0, weight = 0.0;
float *distance;
float root[3];
float tip[3];
float real_co[3];
@@ -2043,7 +2136,7 @@ static void add_verts_to_closest_dgroup(Object *ob, Object *par)
dgroup_skinnable);
/* create an array of floats that will be used for each vert
* to hold the distance to each bone.
* to hold the distance-factor to each bone.
*/
distance = MEM_mallocN(numbones*sizeof(float), "distance");
@@ -2087,21 +2180,10 @@ static void add_verts_to_closest_dgroup(Object *ob, Object *par)
VECCOPY(tip, bone->arm_tail);
Mat4MulVecfl(par->obmat, tip);
/* store the distance from the bone to
* the vert
/* store the distance-factor from the vertex to
* the bone
*/
distance[j] = dist_to_bone(real_co, root, tip);
/* if this is the first bone, or if this
* bone is less than mindist, then set this
* distance to mindist
*/
if (j == 0) {
mindist = distance[j];
}
else if (distance[j] < mindist) {
mindist = distance[j];
}
distance[j]= distfactor_to_bone (real_co, root, tip, bone->rad_head, bone->rad_tail, bone->dist);
}
/* for each deform group ...
@@ -2109,31 +2191,12 @@ static void add_verts_to_closest_dgroup(Object *ob, Object *par)
for (j=0; j < numbones; ++j) {
defgroup = dgrouplist[j];
/* if the cooresponding bone is the closest one
* add the vert to the deform group with weight 1
/* add the vert to the deform group if weight!=0.0
*/
if (distance[j] <= mindist) {
add_vert_to_defgroup (ob, defgroup, i, 1.0, WEIGHT_REPLACE);
}
/* if the cooresponding bone is within 10% of the
* nearest distance, add the vert to the
* deform group with a weight that declines with
* distance
*/
else if (distance[j] <= mindist*1.10) {
if (mindist > 0)
weight = 1.0 - (distance[j] - mindist) / (mindist * 0.10);
add_vert_to_defgroup (ob, defgroup, i, weight, WEIGHT_REPLACE);
}
/* if the cooresponding bone is outside of the 10% tolerance
* then remove the vert from the weight group (if it is
* in that group)
*/
else {
if (distance[j]!=0.0)
add_vert_to_defgroup (ob, defgroup, i, distance[j], WEIGHT_REPLACE);
else
remove_vert_defgroup (ob, defgroup, i);
}
}
}
@@ -2191,7 +2254,7 @@ void create_vgroups_from_armature(Object *ob, Object *par)
static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr)
{
if (bone->flag & BONE_SELECTED) {
bone->flag |= BONE_HIDDEN;
bone->flag |= BONE_HIDDEN_P;
bone->flag &= ~BONE_SELECTED;
}
return 0;
@@ -2211,12 +2274,13 @@ void hide_selected_pose_bones(void)
hide_selected_pose_bone);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
}
static int hide_unselected_pose_bone(Object *ob, Bone *bone, void *ptr)
{
if (~bone->flag & BONE_SELECTED) {
bone->flag |= BONE_HIDDEN;
bone->flag |= BONE_HIDDEN_P;
}
return 0;
}
@@ -2235,12 +2299,13 @@ void hide_unselected_pose_bones(void)
hide_unselected_pose_bone);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
}
static int show_pose_bone(Object *ob, Bone *bone, void *ptr)
{
if (bone->flag & BONE_HIDDEN) {
bone->flag &= ~BONE_HIDDEN;
if (bone->flag & BONE_HIDDEN_P) {
bone->flag &= ~BONE_HIDDEN_P;
bone->flag |= BONE_SELECTED;
}
@@ -2261,6 +2326,7 @@ void show_all_pose_bones(void)
show_pose_bone);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
}
@@ -2317,86 +2383,90 @@ void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
char newname[MAXBONENAME];
char oldname[MAXBONENAME];
/* we alter newname string... so make copy */
BLI_strncpy(newname, newnamep, MAXBONENAME);
/* we use oldname for search... so make copy */
BLI_strncpy(oldname, oldnamep, MAXBONENAME);
/* names better differ! */
if(strncmp(oldnamep, newnamep, MAXBONENAME)) {
/* now check if we're in editmode, we need to find the unique name */
if(G.obedit && G.obedit->data==arm) {
EditBone *eBone;
/* we alter newname string... so make copy */
BLI_strncpy(newname, newnamep, MAXBONENAME);
/* we use oldname for search... so make copy */
BLI_strncpy(oldname, oldnamep, MAXBONENAME);
eBone= editbone_name_exists(oldname);
if(eBone) {
unique_editbone_name (newname);
BLI_strncpy(eBone->name, newname, MAXBONENAME);
}
else return;
}
else {
Bone *bone= get_named_bone (arm, oldname);
/* now check if we're in editmode, we need to find the unique name */
if(G.obedit && G.obedit->data==arm) {
EditBone *eBone;
if(bone) {
unique_bone_name (arm, newname);
BLI_strncpy(bone->name, newname, MAXBONENAME);
}
else return;
}
/* do entire dbase */
for(ob= G.main->object.first; ob; ob= ob->id.next) {
/* we have the object using the armature */
if(arm==ob->data) {
Object *cob;
bAction *act;
bActionChannel *chan;
/* Rename action channel if necessary */
act = ob->action;
if (act && !act->id.lib){
/* Find the appropriate channel */
chan= get_named_actionchannel(act, oldname);
if(chan) BLI_strncpy(chan->name, newname, MAXBONENAME);
eBone= editbone_name_exists(oldname);
if(eBone) {
unique_editbone_name (newname);
BLI_strncpy(eBone->name, newname, MAXBONENAME);
}
else return;
}
else {
Bone *bone= get_named_bone (arm, oldname);
/* Rename the pose channel, if it exists */
if (ob->pose) {
bPoseChannel *pchan = get_pose_channel(ob->pose, oldname);
if (pchan) {
BLI_strncpy (pchan->name, newname, MAXBONENAME);
if(bone) {
unique_bone_name (arm, newname);
BLI_strncpy(bone->name, newname, MAXBONENAME);
}
else return;
}
/* do entire dbase */
for(ob= G.main->object.first; ob; ob= ob->id.next) {
/* we have the object using the armature */
if(arm==ob->data) {
Object *cob;
bAction *act;
bActionChannel *chan;
/* Rename action channel if necessary */
act = ob->action;
if (act && !act->id.lib){
/* Find the appropriate channel */
chan= get_named_actionchannel(act, oldname);
if(chan) BLI_strncpy(chan->name, newname, MAXBONENAME);
}
}
/* and actually do the NLA too */
/* (todo) */
/* Update any object constraints to use the new bone name */
for(cob= G.main->object.first; cob; cob= cob->id.next) {
if(cob->constraints.first)
constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
if (cob->pose) {
bPoseChannel *pchan;
for (pchan = cob->pose->chanbase.first; pchan; pchan=pchan->next) {
constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
/* Rename the pose channel, if it exists */
if (ob->pose) {
bPoseChannel *pchan = get_pose_channel(ob->pose, oldname);
if (pchan) {
BLI_strncpy (pchan->name, newname, MAXBONENAME);
}
}
/* and actually do the NLA too */
/* (todo) */
/* Update any object constraints to use the new bone name */
for(cob= G.main->object.first; cob; cob= cob->id.next) {
if(cob->constraints.first)
constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
if (cob->pose) {
bPoseChannel *pchan;
for (pchan = cob->pose->chanbase.first; pchan; pchan=pchan->next) {
constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
}
}
}
}
}
/* See if an object is parented to this armature */
if (ob->parent && (ob->parent->data == arm)) {
if(ob->partype==PARBONE) {
/* bone name in object */
if (!strcmp(ob->parsubstr, oldname))
BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
}
else if(ob->partype==PARSKEL) {
bDeformGroup *dg;
/* bone name in defgroup */
for (dg=ob->defbase.first; dg; dg=dg->next) {
if(!strcmp(dg->name, oldname))
BLI_strncpy(dg->name, newname, MAXBONENAME);
/* See if an object is parented to this armature */
if (ob->parent && (ob->parent->data == arm)) {
if(ob->partype==PARBONE) {
/* bone name in object */
if (!strcmp(ob->parsubstr, oldname))
BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
}
else if(ob->partype==PARSKEL) {
bDeformGroup *dg;
/* bone name in defgroup */
for (dg=ob->defbase.first; dg; dg=dg->next) {
if(!strcmp(dg->name, oldname))
BLI_strncpy(dg->name, newname, MAXBONENAME);
}
}
}
}

View File

@@ -196,6 +196,13 @@ void del_defgroup (Object *ob)
/* Remove the group */
BLI_freelinkN (&ob->defbase, defgroup);
/* remove all dverts */
if(ob->actdef==0) {
Mesh *me= ob->data;
free_dverts(me->dvert, me->totvert);
me->dvert= NULL;
}
}
void create_dverts(Mesh *me)
@@ -288,7 +295,10 @@ void add_vert_defnr (Object *ob, int def_nr, int vertnum,
/* get the vert
*/
dv = ((Mesh*)ob->data)->dvert + vertnum;
if(((Mesh*)ob->data)->dvert)
dv = ((Mesh*)ob->data)->dvert + vertnum;
else
return;
/* Lets first check to see if this vert is
* already in the weight group -- if so

View File

@@ -976,7 +976,9 @@ void load_editMesh(void)
if(G.totface==0) mface= NULL;
else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh face");
if (G.totvert==0 || me->dvert==NULL) dvert= NULL;
/* are we adding dverts? */
if (G.totvert==0) dvert= NULL;
else if(G.obedit->defbase.first==NULL) dvert= NULL;
else dvert = MEM_callocN(G.totvert*sizeof(MDeformVert), "loadeditMesh3");
if (me->dvert) free_dverts(me->dvert, me->totvert);

View File

@@ -1953,6 +1953,13 @@ void special_editmenu(void)
BIF_undo_push("Shared VertexCol");
}
}
else if(G.f & G_WEIGHTPAINT) {
if(ob->parent && (ob->parent->flag & OB_POSEMODE)) {
nr= pupmenu("Specials%t|Apply Bone Envelopes to VertexGroups %x1");
if(nr==1)
pose_adds_vgroups(ob);
}
}
else {
Base *base, *base_select= NULL;

View File

@@ -3644,7 +3644,6 @@ static char *view3d_modeselect_pup(void)
sprintf(tempstr, formatstr, "Texture Paint", V3D_TEXTUREPAINTMODE_SEL, ICON_TPAINT_HLT);
strcat(string, tempstr);
if ( ((Mesh*)(ob->data))->dvert) {
sprintf(tempstr, formatstr, "Weight Paint", V3D_WEIGHTPAINTMODE_SEL, ICON_WPAINT_HLT);
strcat(string, tempstr);
@@ -3704,6 +3703,7 @@ static char *propfalloff_pup(void)
void do_view3d_buttons(short event)
{
Object *ob= OBACT;
int bit;
/* watch it: if curarea->win does not exist, check that when calling direct drawing routines */
@@ -3778,7 +3778,6 @@ void do_view3d_buttons(short event)
case B_MODESELECT:
if (G.vd->modeselect == V3D_OBJECTMODE_SEL) {
Object *ob= OBACT;
G.vd->flag &= ~V3D_MODE;
G.f &= ~G_VERTEXPAINT; /* Switch off vertex paint */
@@ -3837,7 +3836,7 @@ void do_view3d_buttons(short event)
}
}
else if (G.vd->modeselect == V3D_WEIGHTPAINTMODE_SEL) {
if (!(G.f & G_WEIGHTPAINT) && (OBACT && OBACT->type == OB_MESH) && ((((Mesh*)(OBACT->data))->dvert))) {
if (!(G.f & G_WEIGHTPAINT) && (ob && ob->type == OB_MESH) && ((((Mesh*)(ob->data))->dvert))) {
G.vd->flag &= ~V3D_MODE;
G.f &= ~G_VERTEXPAINT; /* Switch off vertex paint */
G.f &= ~G_TEXTUREPAINT; /* Switch off texture paint */
@@ -3847,7 +3846,6 @@ void do_view3d_buttons(short event)
}
}
else if (G.vd->modeselect == V3D_POSEMODE_SEL) {
Object *ob= OBACT;
if (ob && !(ob->flag & OB_POSEMODE)) {
G.vd->flag &= ~V3D_MODE;
@@ -3944,6 +3942,7 @@ void do_view3d_buttons(short event)
static void view3d_header_pulldowns(uiBlock *block, short *xcoord)
{
Object *ob= OBACT;
short xmax, xco= *xcoord;
/* pull down menus */
@@ -3966,27 +3965,26 @@ static void view3d_header_pulldowns(uiBlock *block, short *xcoord)
xmax= GetButStringLength("Select");
if (G.obedit) {
if (OBACT && OBACT->type == OB_MESH) {
if (ob && ob->type == OB_MESH) {
uiDefPulldownBut(block, view3d_select_meshmenu, NULL, "Select", xco,-2, xmax-3, 24, "");
} else if (OBACT && (OBACT->type == OB_CURVE || OBACT->type == OB_SURF)) {
} else if (ob && (ob->type == OB_CURVE || ob->type == OB_SURF)) {
uiDefPulldownBut(block, view3d_select_curvemenu, NULL, "Select", xco,-2, xmax-3, 24, "");
} else if (OBACT && OBACT->type == OB_FONT) {
} else if (ob && ob->type == OB_FONT) {
uiDefPulldownBut(block, view3d_select_meshmenu, NULL, "Select", xco, -2, xmax-3, 24, "");
} else if (OBACT && OBACT->type == OB_MBALL) {
} else if (ob && ob->type == OB_MBALL) {
uiDefPulldownBut(block, view3d_select_metaballmenu, NULL, "Select", xco,-2, xmax-3, 24, "");
} else if (OBACT && OBACT->type == OB_LATTICE) {
} else if (ob && ob->type == OB_LATTICE) {
uiDefPulldownBut(block, view3d_select_latticemenu, NULL, "Select", xco,-2, xmax-3, 24, "");
} else if (OBACT && OBACT->type == OB_ARMATURE) {
} else if (ob && ob->type == OB_ARMATURE) {
uiDefPulldownBut(block, view3d_select_armaturemenu, NULL, "Select", xco,-2, xmax-3, 24, "");
}
} else if (G.f & G_FACESELECT) {
if (OBACT && OBACT->type == OB_MESH) {
if (ob && ob->type == OB_MESH) {
uiDefPulldownBut(block, view3d_select_faceselmenu, NULL, "Select", xco,-2, xmax-3, 24, "");
}
} else if ((G.f & G_VERTEXPAINT) || (G.f & G_TEXTUREPAINT) || (G.f & G_WEIGHTPAINT)) {
uiDefBut(block, LABEL,0,"", xco, 0, xmax, 20, 0, 0, 0, 0, 0, "");
} else {
Object *ob= OBACT;
if (ob && (ob->flag & OB_POSEMODE))
uiDefPulldownBut(block, view3d_select_pose_armaturemenu, NULL, "Select", xco,-2, xmax-3, 24, "");
@@ -3996,31 +3994,31 @@ static void view3d_header_pulldowns(uiBlock *block, short *xcoord)
xco+= xmax;
if (G.obedit) {
if (OBACT && OBACT->type == OB_MESH) {
if (ob && ob->type == OB_MESH) {
xmax= GetButStringLength("Mesh");
uiDefPulldownBut(block, view3d_edit_meshmenu, NULL, "Mesh", xco,-2, xmax-3, 24, "");
xco+= xmax;
} else if (OBACT && OBACT->type == OB_CURVE) {
} else if (ob && ob->type == OB_CURVE) {
xmax= GetButStringLength("Curve");
uiDefPulldownBut(block, view3d_edit_curvemenu, NULL, "Curve", xco,-2, xmax-3, 24, "");
xco+= xmax;
} else if (OBACT && OBACT->type == OB_SURF) {
} else if (ob && ob->type == OB_SURF) {
xmax= GetButStringLength("Surface");
uiDefPulldownBut(block, view3d_edit_curvemenu, NULL, "Surface", xco,-2, xmax-3, 24, "");
xco+= xmax;
} else if (OBACT && OBACT->type == OB_FONT) {
} else if (ob && ob->type == OB_FONT) {
xmax= GetButStringLength("Text");
uiDefPulldownBut(block, view3d_edit_textmenu, NULL, "Text", xco,-2, xmax-3, 24, "");
xco+= xmax;
} else if (OBACT && OBACT->type == OB_MBALL) {
} else if (ob && ob->type == OB_MBALL) {
xmax= GetButStringLength("Metaball");
uiDefPulldownBut(block, view3d_edit_metaballmenu, NULL, "Metaball", xco,-2, xmax-3, 24, "");
xco+= xmax;
} else if (OBACT && OBACT->type == OB_LATTICE) {
} else if (ob && ob->type == OB_LATTICE) {
xmax= GetButStringLength("Lattice");
uiDefPulldownBut(block, view3d_edit_latticemenu, NULL, "Lattice", xco,-2, xmax-3, 24, "");
xco+= xmax;
} else if (OBACT && OBACT->type == OB_ARMATURE) {
} else if (ob && ob->type == OB_ARMATURE) {
xmax= GetButStringLength("Armature");
uiDefPulldownBut(block, view3d_edit_armaturemenu, NULL, "Armature", xco,-2, xmax-3, 24, "");
xco+= xmax;
@@ -4032,14 +4030,12 @@ static void view3d_header_pulldowns(uiBlock *block, short *xcoord)
xco+= xmax;
}
else if (G.f & G_FACESELECT) {
if (OBACT && OBACT->type == OB_MESH) {
if (ob && ob->type == OB_MESH) {
xmax= GetButStringLength("Face");
uiDefPulldownBut(block, view3d_faceselmenu, NULL, "Face", xco,-2, xmax-3, 24, "");
xco+= xmax;
}
} else {
Object *ob= OBACT;
if (ob && (ob->flag & OB_POSEMODE)) {
xmax= GetButStringLength("Pose");
uiDefPulldownBut(block, view3d_pose_armaturemenu, NULL, "Pose", xco,-2, xmax-3, 24, "");

View File

@@ -1235,7 +1235,7 @@ static int tree_element_active_posechannel(TreeElement *te, TreeStoreElem *tsele
bPoseChannel *pchan= te->directdata;
if(set) {
if(!(pchan->bone->flag & BONE_HIDDEN)) {
if(!(pchan->bone->flag & BONE_HIDDEN_P)) {
if(G.qual & LR_SHIFTKEY) deselectall_posearmature(ob, 2); // 2 = clear active tag
else deselectall_posearmature(ob, 0); // 0 = deselect
@@ -1260,7 +1260,7 @@ static int tree_element_active_bone(TreeElement *te, TreeStoreElem *tselem, int
Bone *bone= te->directdata;
if(set) {
if(!(bone->flag & BONE_HIDDEN)) {
if(!(bone->flag & BONE_HIDDEN_P)) {
if(G.qual & LR_SHIFTKEY) deselectall_posearmature(OBACT, 2); // 2 is clear active tag
else deselectall_posearmature(OBACT, 0);
bone->flag |= BONE_SELECTED|BONE_ACTIVE;
@@ -1287,16 +1287,19 @@ static int tree_element_active_ebone(TreeElement *te, TreeStoreElem *tselem, int
EditBone *ebone= te->directdata;
if(set) {
if(G.qual & LR_SHIFTKEY) deselectall_armature(2); // only clear active tag
else deselectall_armature(0); // deselect
if(!(ebone->flag & BONE_HIDDEN_A)) {
ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_ACTIVE;
// flush to parent?
if(ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) ebone->parent->flag |= BONE_TIPSEL;
if(G.qual & LR_SHIFTKEY) deselectall_armature(2); // only clear active tag
else deselectall_armature(0); // deselect
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWOOPS, 0);
allqueue(REDRAWACTION, 0);
ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_ACTIVE;
// flush to parent?
if(ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) ebone->parent->flag |= BONE_TIPSEL;
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWOOPS, 0);
allqueue(REDRAWACTION, 0);
}
}
else {
if (ebone->flag & BONE_SELECTED) return 1;

View File

@@ -37,6 +37,8 @@
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -45,6 +47,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_deform.h"
#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_global.h"
@@ -54,6 +57,7 @@
#include "BIF_editarmature.h"
#include "BIF_editaction.h"
#include "BIF_editconstraint.h"
#include "BIF_editdeform.h"
#include "BIF_gl.h"
#include "BIF_graphics.h"
#include "BIF_interface.h"
@@ -527,6 +531,62 @@ void paste_posebuf (int flip)
BIF_undo_push("Paste Action Pose");
}
/* ********************************************** */
void pose_adds_vgroups(Object *meshobj)
{
Object *poseobj= meshobj->parent;
bPoseChannel *pchan;
Bone *bone;
bDeformGroup *dg;
Mesh *me= meshobj->data;
MVert *mvert;
float head[3], tail[3], vec[3], fac;
int i;
if(poseobj==NULL || (poseobj->flag & OB_POSEMODE)==0) return;
for(pchan= poseobj->pose->chanbase.first; pchan; pchan= pchan->next) {
bone= pchan->bone;
if(bone->flag & (BONE_SELECTED)) {
/* check if mesh has vgroups */
dg= get_named_vertexgroup(meshobj, bone->name);
if(dg==NULL)
dg= add_defgroup_name(meshobj, bone->name);
/* get the root of the bone in global coords */
VECCOPY(head, bone->arm_head);
Mat4MulVecfl(poseobj->obmat, head);
/* get the tip of the bone in global coords */
VECCOPY(tail, bone->arm_tail);
Mat4MulVecfl(poseobj->obmat, tail);
/* todo; get the optimal vertices instead of mverts */
mvert= me->mvert;
for ( i=0 ; i < me->totvert ; i++ , mvert++) {
VECCOPY(vec, mvert->co);
Mat4MulVecfl(meshobj->obmat, vec);
/* get the distance-factor from the vertex to bone */
fac= distfactor_to_bone (vec, head, tail, bone->rad_head, bone->rad_tail, bone->dist);
/* add to vgroup. this call also makes me->dverts */
if(fac!=0.0f)
add_vert_to_defgroup (meshobj, dg, i, fac, WEIGHT_REPLACE);
else
remove_vert_defgroup (meshobj, dg, i);
}
}
}
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
DAG_object_flush_update(G.scene, meshobj, OB_RECALC_DATA); // and all its relations
}
/* ********************************************** */

View File

@@ -54,6 +54,7 @@
#include "BLI_linklist.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_image_types.h"
#include "DNA_ipo_types.h"
@@ -1306,6 +1307,14 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else if((G.qual==0))
hide_mball(0);
}
else if(G.obedit->type==OB_ARMATURE) {
if (G.qual==0)
hide_selected_armature_bones();
else if (G.qual==LR_SHIFTKEY)
hide_unselected_armature_bones();
else if (G.qual==LR_ALTKEY)
show_all_armature_bones();
}
}
else if(G.f & G_FACESELECT)
hide_tface();
@@ -1568,8 +1577,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else if(G.obedit) {
if(G.qual==LR_ALTKEY) {
if(G.obedit->type==OB_ARMATURE)
if(G.obedit->type==OB_ARMATURE) {
initTransform(TFM_BONESIZE, CTX_NONE);
}
else
initTransform(TFM_SHRINKFATTEN, CTX_NONE);
Transform();
@@ -1581,7 +1591,15 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else if(G.qual==LR_SHIFTKEY)
snapmenu();
else if(G.qual==0) {
initTransform(TFM_RESIZE, CTX_NONE);
if(G.obedit->type==OB_ARMATURE) {
bArmature *arm= G.obedit->data;
if(arm->drawtype==ARM_ENVELOPE)
initTransform(TFM_BONE_ENVELOPE, CTX_NONE);
else
initTransform(TFM_RESIZE, CTX_NONE);
}
else
initTransform(TFM_RESIZE, CTX_NONE);
Transform();
}
else if(G.qual==(LR_SHIFTKEY|LR_CTRLKEY)){
@@ -1591,6 +1609,17 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
else if(G.qual==LR_ALTKEY) {
if(G.f & G_WEIGHTPAINT)
ob= ob->parent;
if(ob && (ob->flag & OB_POSEMODE)) {
bArmature *arm= ob->data;
if( ELEM(arm->drawtype, ARM_B_BONE, ARM_ENVELOPE)) {
initTransform(TFM_BONESIZE, CTX_NONE);
Transform();
break;
}
}
if(okee("Clear size")) {
clear_object('s');
}

View File

@@ -47,18 +47,19 @@
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
#include "DNA_ipo_types.h" /* some silly ipo flag */
#include "DNA_listBase.h"
#include "DNA_userdef_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h" /* PET modes */
#include "DNA_screen_types.h" /* area dimensions */
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
#include "DNA_ipo_types.h" /* some silly ipo flag */
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
#include "BIF_editview.h" /* arrows_move_cursor */
#include "BIF_gl.h"
@@ -285,6 +286,10 @@ static char *transform_to_undostr(TransInfo *t)
return "Push/Pull";
case TFM_CREASE:
return "Crease";
case TFM_BONESIZE:
return "Bone Width";
case TFM_BONE_ENVELOPE:
return "Bone Envelope";
}
return "Transform";
}
@@ -361,29 +366,39 @@ static void transformEvent(unsigned short event, short val) {
Trans.state = TRANS_CONFIRM;
break;
case GKEY:
restoreTransObjects(&Trans);
initTransModeFlags(&Trans, TFM_TRANSLATION);
initTranslation(&Trans);
Trans.redraw = 1;
/* only switch when... */
if( ELEM3(Trans.mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) {
restoreTransObjects(&Trans);
initTransModeFlags(&Trans, TFM_TRANSLATION);
initTranslation(&Trans);
Trans.redraw = 1;
}
break;
case SKEY:
restoreTransObjects(&Trans);
initTransModeFlags(&Trans, TFM_RESIZE);
initResize(&Trans);
Trans.redraw = 1;
/* only switch when... */
if( ELEM3(Trans.mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) {
restoreTransObjects(&Trans);
initTransModeFlags(&Trans, TFM_RESIZE);
initResize(&Trans);
Trans.redraw = 1;
}
break;
case RKEY:
if (Trans.mode == TFM_ROTATION) {
restoreTransObjects(&Trans);
initTransModeFlags(&Trans, TFM_TRACKBALL);
initTrackball(&Trans);
/* only switch when... */
if( ELEM4(Trans.mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) {
if (Trans.mode == TFM_ROTATION) {
restoreTransObjects(&Trans);
initTransModeFlags(&Trans, TFM_TRACKBALL);
initTrackball(&Trans);
}
else {
restoreTransObjects(&Trans);
initTransModeFlags(&Trans, TFM_ROTATION);
initRotation(&Trans);
}
Trans.redraw = 1;
}
else {
restoreTransObjects(&Trans);
initTransModeFlags(&Trans, TFM_ROTATION);
initRotation(&Trans);
}
Trans.redraw = 1;
break;
case CKEY:
if (G.qual & LR_ALTKEY) {
@@ -595,7 +610,16 @@ void initTransform(int mode, int context) {
initCrease(&Trans);
break;
case TFM_BONESIZE:
initBoneSize(&Trans);
{ /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */
bArmature *arm= Trans.poseobj->data;
if(arm->drawtype==ARM_ENVELOPE)
initBoneEnvelope(&Trans);
else
initBoneSize(&Trans);
}
break;
case TFM_BONE_ENVELOPE:
initBoneEnvelope(&Trans);
break;
}
}
@@ -676,6 +700,13 @@ void initManipulator(int mode)
Trans.context = CTX_NONE;
/* automatic switch to scaling bone envelopes */
if(mode==TFM_RESIZE && G.obedit && G.obedit->type==OB_ARMATURE) {
bArmature *arm= G.obedit->data;
if(arm->drawtype==ARM_ENVELOPE)
mode= TFM_BONE_ENVELOPE;
}
initTrans(&Trans); // internal data, mouse, vectors
initTransModeFlags(&Trans, mode); // modal settings in struct Trans
@@ -2251,7 +2282,7 @@ void Mirror(short mode)
scrarea_queue_headredraw(curarea);
}
/* ******************** EditBone scaling *************** */
/* ******************** EditBone (B-bone) width scaling *************** */
static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3])
{
@@ -2357,10 +2388,86 @@ void initBoneSize(TransInfo *t)
t->snap[2] = t->snap[1] * 0.1f;
t->transform = BoneSize;
t->fac = (float)sqrt( (float)(
(t->center2d[1] - t->imval[1])*(t->center2d[1] - t->imval[1])
+
(t->center2d[0] - t->imval[0])*(t->center2d[0] - t->imval[0])
) );
(t->center2d[1] - t->imval[1])*(t->center2d[1] - t->imval[1])
+
(t->center2d[0] - t->imval[0])*(t->center2d[0] - t->imval[0])
) );
if(t->fac==0.0f) t->fac= 1.0f; // prevent Inf
}
/* ******************** EditBone envelope *************** */
int BoneEnvelope(TransInfo *t, short mval[2])
{
TransData *td = t->data;
float ratio;
int i;
char str[50];
if(t->flag & T_SHIFT_MOD) {
/* calculate ratio for shiftkey pos, and for total, and blend these for precision */
float dx= (float)(t->center2d[0] - t->shiftmval[0]);
float dy= (float)(t->center2d[1] - t->shiftmval[1]);
ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
dx= (float)(t->center2d[0] - mval[0]);
dy= (float)(t->center2d[1] - mval[1]);
ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
}
else {
float dx= (float)(t->center2d[0] - mval[0]);
float dy= (float)(t->center2d[1] - mval[1]);
ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
}
snapGrid(t, &ratio);
applyNumInput(&t->num, &ratio);
/* header print for NumInput */
if (hasNumInput(&t->num)) {
char c[20];
outputNumInput(&(t->num), c);
sprintf(str, "Envelope: %s", c);
}
else {
sprintf(str, "Envelope: %3f", ratio);
}
for(i = 0 ; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
if(td->val) *td->val= td->ival*ratio;
}
recalcData(t);
headerprint(str);
force_draw(0);
if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
return 1;
}
void initBoneEnvelope(TransInfo *t)
{
t->idx_max = 0;
t->num.idx_max = 0;
t->snap[0] = 0.0f;
t->snap[1] = 0.1f;
t->snap[2] = t->snap[1] * 0.1f;
t->transform = BoneEnvelope;
t->fac = (float)sqrt( (float)(
(t->center2d[1] - t->imval[1])*(t->center2d[1] - t->imval[1])
+
(t->center2d[0] - t->imval[0])*(t->center2d[0] - t->imval[0])
) );
if(t->fac==0.0f) t->fac= 1.0f; // prevent Inf
}

View File

@@ -446,6 +446,22 @@ static int add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tra
Mat3MulMat3(td->axismtx, omat, pmat);
Mat3Ortho(td->axismtx);
if(t->mode==TFM_BONESIZE) {
bArmature *arm= t->poseobj->data;
if(arm->drawtype==ARM_ENVELOPE) {
td->loc= NULL;
td->val= &bone->dist;
td->ival= bone->dist;
}
else {
// abusive storage of scale in the loc pointer :)
td->loc= &bone->xwidth;
VECCOPY (td->iloc, td->loc);
td->val= NULL;
}
}
return 1;
}
}
@@ -466,9 +482,11 @@ static void createTransPose(Object *ob, TransInfo *t)
arm=get_armature (ob);
if (arm==NULL || ob->pose==NULL) return;
if (arm->flag & ARM_RESTPOS){
notice ("Pose edit not possible while Rest Position is enabled");
return;
if (arm->flag & ARM_RESTPOS) {
if(t->mode!=TFM_BONESIZE) {
notice ("Pose edit not possible while Rest Position is enabled");
return;
}
}
if (!(ob->lay & G.vd->lay)) return;
@@ -507,6 +525,7 @@ static void createTransPose(Object *ob, TransInfo *t)
static void createTransArmatureVerts(TransInfo *t)
{
EditBone *ebo;
bArmature *arm= G.obedit->data;
TransData *td;
float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
@@ -532,11 +551,57 @@ static void createTransArmatureVerts(TransInfo *t)
td = t->data = MEM_mallocN(t->total*sizeof(TransData), "TransEditBone");
for (ebo=G.edbo.first;ebo;ebo=ebo->next){
if (t->mode==TFM_BONESIZE) {
ebo->oldlength= ebo->length; // might be used for scaling
if (t->mode==TFM_BONE_ENVELOPE) {
if (ebo->flag & BONE_ROOTSEL){
td->val= &ebo->rad_head;
td->ival= *td->val;
VECCOPY (td->center, ebo->head);
td->flag= TD_SELECTED;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
td->loc = NULL;
td->ext = NULL;
td->tdi = NULL;
td++;
}
if (ebo->flag & BONE_TIPSEL){
td->val= &ebo->rad_tail;
td->ival= *td->val;
VECCOPY (td->center, ebo->tail);
td->flag= TD_SELECTED;
Mat3CpyMat3(td->smtx, smtx);
Mat3CpyMat3(td->mtx, mtx);
td->loc = NULL;
td->ext = NULL;
td->tdi = NULL;
td++;
}
}
else if (t->mode==TFM_BONESIZE) {
if (ebo->flag & BONE_SELECTED) {
// abusive storage of scale in the loc pointer :)
td->loc= &ebo->xwidth;
VECCOPY (td->iloc, td->loc);
if(arm->drawtype==ARM_ENVELOPE) {
td->loc= NULL;
td->val= &ebo->dist;
td->ival= ebo->dist;
}
else {
// abusive storage of scale in the loc pointer :)
td->loc= &ebo->xwidth;
VECCOPY (td->iloc, td->loc);
td->val= NULL;
}
VECCOPY (td->center, ebo->head);
td->flag= TD_SELECTED;
@@ -551,7 +616,6 @@ static void createTransArmatureVerts(TransInfo *t)
td->ext = NULL;
td->tdi = NULL;
td->val = NULL;
td++;
}
@@ -1363,7 +1427,10 @@ void special_aftertrans_update(TransInfo *t)
int redrawipo=0;
int cancelled= (t->state == TRANS_CANCEL);
if(G.obedit); // nothing
if(G.obedit) {
if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
allqueue(REDRAWBUTSEDIT, 0);
}
else if( (t->flag & T_POSE) && t->poseobj) {
bArmature *arm;
bAction *act;
@@ -1415,6 +1482,10 @@ void special_aftertrans_update(TransInfo *t)
ob->recalc= 0; // is set on OK position already by recalcData()
}
/* do not call DAG_object_flush_update always, we dont want actions to update, for inserting keys */
if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
allqueue(REDRAWBUTSEDIT, 0);
}
else {
base= FIRSTBASE;
@@ -1636,10 +1707,11 @@ void createTransData(TransInfo *t)
}
t->flag |= T_EDIT;
/* exception... hackish, we want bonescale to use bone orientation matrix (ton) */
/* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
if(t->mode==TFM_BONESIZE) {
t->flag &= ~T_EDIT;
t->flag |= T_POSE;
t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
}
}
else if (ob && (ob->flag & OB_POSEMODE)) {

View File

@@ -127,12 +127,16 @@ static void transform_armature_mirror_update(void)
eboflip->tail[0]= -ebo->tail[0];
eboflip->tail[1]= ebo->tail[1];
eboflip->tail[2]= ebo->tail[2];
eboflip->rad_tail= ebo->rad_tail;
}
if(ebo->flag & BONE_ROOTSEL) {
eboflip->head[0]= -ebo->head[0];
eboflip->head[1]= ebo->head[1];
eboflip->head[2]= ebo->head[2];
eboflip->rad_head= ebo->rad_head;
}
if(ebo->flag & BONE_SELECTED)
eboflip->dist= ebo->dist;
}
}
}
@@ -176,6 +180,17 @@ void recalcData(TransInfo *t)
VECCOPY (ebo->parent->tail, ebo->head);
}
}
if(arm->drawtype==ARM_ENVELOPE) {
if(ebo->oldlength==0.0f) {
ebo->rad_head= 0.25f*ebo->length;
ebo->rad_tail= 0.10f*ebo->length;
if(ebo->parent) {
if(ebo->rad_head > ebo->parent->rad_tail)
ebo->rad_head= ebo->parent->rad_tail;
}
}
}
}
if(arm->flag & ARM_MIRROR_EDIT)
transform_armature_mirror_update();
@@ -260,9 +275,8 @@ void initTransModeFlags(TransInfo *t, int mode)
t->flag |= T_NO_CONSTRAINT;
break;
case TFM_SHEAR:
t->flag |= T_NO_CONSTRAINT;
break;
case TFM_CREASE:
case TFM_BONE_ENVELOPE:
t->flag |= T_NO_CONSTRAINT;
break;
}

View File

@@ -809,6 +809,7 @@ void setwinmatrixview3d(rctf *rect) /* rect: for picking */
else y1= -G.vd->dist;
y2= -y1;
far*= 0.5; // otherwise too extreme low zbuffer quality
near= -far;
orth= 1;
}