Integration of new IK lib features in Armature Poses.
Best is to forget yesterday's commit and old docs. New docs are underway... Here's how IK works now; - IK chains can go all the way to the furthest parent Bone. Disregarding the old option "IK to Parent" and disgregarding whether a Bone has an offset to its parent (offsets now work for IK, so you can also make T-bones). - The old "IK to Parent" option now only does what it should do: it denotes whether a Bone is directly connected to a Parent Bone, or not. In the UI and in code this option is now called "Connected". - You can also define yourself which Bone will become the "Root" for an IK chain. This can be any Parent of the IK tip (where the IK constraint is). By default it goes all the way, unless you set a value for the new IK Constraint Panel option "Chain Lenght". - "Tree IK" now is detected automatic, when multiple IK Roots are on the same Bone, and when there's a branched structure. Multiple IK's on a single chain (no branches) is still executed as usual, doing the IK's sequentially. - Note: Branched structures, with _partial_ overlapping IK chains, that don't share the same Root will possibly disconnect branches. - When you select a Bone with IK, it now draws a yellow dashed line to its Root. - The IK options "Location Weight" and "Rotation Weight" are relative, in case there's a Tree IK structure. These weights cannot be set to zero. To animate or disable IK Targets, use the "Influence" slider. - This new IK is backwards and upwards compatible for Blender files. Of course, the new features won't show in older Blender binaries! :) Other changes & notes; - In PoseMode, the Constraint Panel now also draws in Editing Buttons, next to the Bones Panel. - IK Constraint Panel was redesigned... it's still a bit squished - Buttons "No X DoF" is now called "Lock X". This to follow convention to name options positive. - Added Undo push for Make/Clear Parent in Editmode Armature - Use CTRL+P "Make Parent" on a single selected Bone to make it become connected (ALT+P had already "Disconnect"). On todo next; Visualizing & review of Bone DoF limits and stiffness
This commit is contained in:
parent
fa443a5f01
commit
85efe767f0
|
@ -273,7 +273,7 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan
|
|||
/* pose should be entirely OK */
|
||||
void update_pose_constraint_flags(bPose *pose)
|
||||
{
|
||||
bPoseChannel *pchan;
|
||||
bPoseChannel *pchan, *parchan;
|
||||
bConstraint *con;
|
||||
|
||||
/* clear */
|
||||
|
@ -284,7 +284,23 @@ void update_pose_constraint_flags(bPose *pose)
|
|||
for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
|
||||
for(con= pchan->constraints.first; con; con= con->next) {
|
||||
if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
|
||||
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
|
||||
|
||||
pchan->constflag |= PCHAN_HAS_IK;
|
||||
/* negative rootbone = recalc rootbone index. used in do_versions */
|
||||
if(data->rootbone<0) {
|
||||
data->rootbone= 0;
|
||||
|
||||
if(data->flag & CONSTRAINT_IK_TIP) parchan= pchan;
|
||||
else parchan= pchan->parent;
|
||||
|
||||
while(parchan) {
|
||||
data->rootbone++;
|
||||
if((parchan->bone->flag & BONE_CONNECTED)==0)
|
||||
break;
|
||||
parchan= parchan->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
else pchan->constflag |= PCHAN_HAS_CONST;
|
||||
}
|
||||
|
|
|
@ -432,7 +432,7 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan)
|
|||
hlength2= bone->ease2*length*0.390464f;
|
||||
|
||||
/* evaluate next and prev bones */
|
||||
if(bone->flag & BONE_IK_TOPARENT)
|
||||
if(bone->flag & BONE_CONNECTED)
|
||||
prev= pchan->parent;
|
||||
else
|
||||
prev= NULL;
|
||||
|
@ -912,8 +912,8 @@ static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int
|
|||
|
||||
for(bone= bone->childbase.first; bone; bone= bone->next) {
|
||||
counter= rebuild_pose_bone(pose, bone, pchan, counter);
|
||||
/* for quick detecting of next bone in chain */
|
||||
if(bone->flag & BONE_IK_TOPARENT)
|
||||
/* for quick detecting of next bone in chain, only b-bone uses it now */
|
||||
if(bone->flag & BONE_CONNECTED)
|
||||
pchan->child= get_pose_channel(pose, bone->name);
|
||||
}
|
||||
|
||||
|
@ -990,50 +990,53 @@ static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip)
|
|||
if(data->tar==NULL) return;
|
||||
if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0) return;
|
||||
|
||||
/* exclude tip from chain? */
|
||||
if(!(data->flag & CONSTRAINT_IK_TIP))
|
||||
pchan_tip= pchan_tip->parent;
|
||||
|
||||
/* Find the chain's root & count the segments needed */
|
||||
for (curchan = pchan_tip; curchan; curchan=curchan->parent){
|
||||
pchan_root = curchan;
|
||||
|
||||
curchan->flag |= POSE_CHAIN; // don't forget to clear this
|
||||
chanlist[segcount]=curchan;
|
||||
segcount++;
|
||||
|
||||
/* exclude tip from chain? */
|
||||
if(curchan==pchan_tip) {
|
||||
if(!(data->flag & CONSTRAINT_IK_TIP)) segcount--;
|
||||
}
|
||||
|
||||
if(segcount>255) break; // also weak
|
||||
|
||||
if (!(curchan->bone->flag & BONE_IK_TOPARENT))
|
||||
break;
|
||||
if(segcount==data->rootbone || segcount>255) break; // 255 is weak
|
||||
}
|
||||
if (!segcount) return;
|
||||
|
||||
/* setup the chain data */
|
||||
chain = NULL;
|
||||
|
||||
/* if tree-IK, look for mathing chain */
|
||||
if(data->flag & CONSTRAINT_IK_TREE)
|
||||
for(chain= pchan_root->chain.first; chain; chain= chain->next)
|
||||
if(chain->tree) break;
|
||||
|
||||
/* we make tree-IK, unless all existing targets are in this chain */
|
||||
for(chain= pchan_root->chain.first; chain; chain= chain->next) {
|
||||
for(target= chain->targets.first; target; target= target->next) {
|
||||
curchan= chain->pchanchain[target->tip];
|
||||
if(curchan->flag & POSE_CHAIN)
|
||||
curchan->flag &= ~POSE_CHAIN;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if(target) break;
|
||||
}
|
||||
|
||||
/* create a target */
|
||||
target= MEM_callocN(sizeof(PoseTarget), "posetarget");
|
||||
target->con= con;
|
||||
pchan_tip->flag &= ~POSE_CHAIN;
|
||||
|
||||
if(chain==NULL) {
|
||||
/* make new chain */
|
||||
chain= MEM_callocN(sizeof(PoseChain), "posechain");
|
||||
|
||||
chain->tree= data->flag & CONSTRAINT_IK_TREE;
|
||||
chain->tolerance= data->tolerance;
|
||||
chain->iterations= data->iterations;
|
||||
chain->totchannel= segcount;
|
||||
|
||||
chain->pchanchain= MEM_callocN(segcount*sizeof(void *), "channel chain");
|
||||
for(a=0; a<segcount; a++)
|
||||
for(a=0; a<segcount; a++) {
|
||||
chain->pchanchain[a]= chanlist[segcount-a-1];
|
||||
|
||||
}
|
||||
target->tip= segcount-1;
|
||||
|
||||
/* AND! link the chain to the root */
|
||||
|
@ -1048,7 +1051,6 @@ static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip)
|
|||
for(a=0; a<size && chain->pchanchain[a]==chanlist[segcount-a-1]; a++);
|
||||
|
||||
segcount= segcount-a;
|
||||
|
||||
target->tip= chain->totchannel + segcount - 1;
|
||||
|
||||
if (segcount > 0) {
|
||||
|
@ -1063,7 +1065,7 @@ static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip)
|
|||
/* add new pose channels at the end, in reverse order */
|
||||
for(a=0; a<segcount; a++)
|
||||
chain->pchanchain[chain->totchannel+a]= chanlist[segcount-a-1];
|
||||
|
||||
|
||||
chain->totchannel= newsize;
|
||||
}
|
||||
|
||||
|
@ -1129,7 +1131,7 @@ static void execute_posechain(Object *ob, PoseChain *chain)
|
|||
/* get the matrix that transforms from prevbone into this bone */
|
||||
Mat3CpyMat4(R_bonemat, pchan->pose_mat);
|
||||
|
||||
if(pchan->parent && (bone->flag & BONE_IK_TOPARENT)) {
|
||||
if(a>0 && pchan->parent) {
|
||||
Mat3CpyMat4(R_parmat, pchan->parent->pose_mat);
|
||||
}
|
||||
else
|
||||
|
@ -1138,8 +1140,7 @@ static void execute_posechain(Object *ob, PoseChain *chain)
|
|||
Mat3Inv(iR_parmat, R_parmat);
|
||||
|
||||
/* gather transformations for this IK segment */
|
||||
start[0]= start[1]= start[2]= 0.0;
|
||||
|
||||
|
||||
/* change length based on bone size */
|
||||
Mat3ToSize(R_bonemat, bonesize);
|
||||
length= bone->length*bonesize[1];
|
||||
|
@ -1155,6 +1156,14 @@ static void execute_posechain(Object *ob, PoseChain *chain)
|
|||
Mat3Ortho(rest_basis);
|
||||
Mat3Ortho(basis);
|
||||
|
||||
/* Bone offset */
|
||||
if(a>0 && pchan->parent) {
|
||||
VECCOPY(start, bone->head);
|
||||
// Mat3MulVecfl(R_parmat, start);
|
||||
}
|
||||
else
|
||||
start[0]= start[1]= start[2]= 0.0f;
|
||||
|
||||
IK_SetTransform(seg, start, rest_basis, basis, length);
|
||||
|
||||
if (pchan->ikflag & BONE_IK_XLIMIT)
|
||||
|
@ -1272,7 +1281,7 @@ void chan_calc_mat(bPoseChannel *chan)
|
|||
|
||||
/* prevent action channels breaking chains */
|
||||
/* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */
|
||||
if (chan->bone==NULL || !(chan->bone->flag & BONE_IK_TOPARENT)) {
|
||||
if (chan->bone==NULL || !(chan->bone->flag & BONE_CONNECTED)) {
|
||||
VECCOPY(chan->chan_mat[3], chan->loc);
|
||||
}
|
||||
|
||||
|
@ -1398,7 +1407,7 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan)
|
|||
Mat4MulMat4 (pchan->pose_mat, conOb.obmat, ob->imat);
|
||||
|
||||
/* prevent constraints breaking a chain */
|
||||
if(pchan->bone->flag & BONE_IK_TOPARENT)
|
||||
if(pchan->bone->flag & BONE_CONNECTED)
|
||||
VECCOPY(pchan->pose_mat[3], vec);
|
||||
|
||||
}
|
||||
|
@ -1444,43 +1453,44 @@ void where_is_pose (Object *ob)
|
|||
|
||||
/* 1. construct the PoseChains, clear flags */
|
||||
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
||||
pchan->flag &= ~POSE_DONE;
|
||||
pchan->flag &= ~(POSE_DONE|POSE_CHAIN);
|
||||
if(pchan->constflag & PCHAN_HAS_IK) // flag is set on editing constraints
|
||||
initialize_posechain(ob, pchan); // will attach it to root!
|
||||
}
|
||||
|
||||
/* 2. the main loop, channels are already hierarchical sorted from root to children */
|
||||
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
||||
if(!(pchan->flag & POSE_DONE)) {
|
||||
/* 3. if we find an IK root, we handle it separated */
|
||||
if(pchan->chain.first) {
|
||||
while(pchan->chain.first) {
|
||||
PoseChain *chain= pchan->chain.first;
|
||||
int a;
|
||||
|
||||
/* 4. walk over the chain for regular solving */
|
||||
for(a=0; a<chain->totchannel; a++) {
|
||||
if(!(chain->pchanchain[a]->flag & POSE_DONE)) // successive chains can set the flag
|
||||
where_is_pose_bone(ob, chain->pchanchain[a]);
|
||||
}
|
||||
/* 5. execute the IK solver, applying differences to
|
||||
the channels and setting POSE_DONE */
|
||||
execute_posechain(ob, chain);
|
||||
|
||||
/* 6. apply the differences to the channels, we calculate the original differences first */
|
||||
for(a=0; a<chain->totchannel; a++)
|
||||
make_dmats(chain->pchanchain[a]);
|
||||
|
||||
for(a=0; a<chain->totchannel; a++)
|
||||
/* sets POSE_DONE */
|
||||
where_is_ik_bone(chain->pchanchain[a], chain->basis_change[a]);
|
||||
|
||||
/* 7. and free */
|
||||
BLI_remlink(&pchan->chain, chain);
|
||||
free_posechain(chain);
|
||||
|
||||
/* 3. if we find an IK root, we handle it separated */
|
||||
if(pchan->chain.first) {
|
||||
while(pchan->chain.first) {
|
||||
PoseChain *chain= pchan->chain.first;
|
||||
int a;
|
||||
|
||||
/* 4. walk over the chain for regular solving */
|
||||
for(a=0; a<chain->totchannel; a++) {
|
||||
if(!(chain->pchanchain[a]->flag & POSE_DONE)) // successive chains can set the flag
|
||||
where_is_pose_bone(ob, chain->pchanchain[a]);
|
||||
}
|
||||
/* 5. execute the IK solver */
|
||||
execute_posechain(ob, chain);
|
||||
|
||||
/* 6. apply the differences to the channels,
|
||||
we need to calculate the original differences first */
|
||||
for(a=0; a<chain->totchannel; a++)
|
||||
make_dmats(chain->pchanchain[a]);
|
||||
|
||||
for(a=0; a<chain->totchannel; a++)
|
||||
/* sets POSE_DONE */
|
||||
where_is_ik_bone(chain->pchanchain[a], chain->basis_change[a]);
|
||||
|
||||
/* 7. and free */
|
||||
BLI_remlink(&pchan->chain, chain);
|
||||
free_posechain(chain);
|
||||
}
|
||||
else where_is_pose_bone(ob, pchan);
|
||||
}
|
||||
else if(!(pchan->flag & POSE_DONE)) {
|
||||
where_is_pose_bone(ob, pchan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1526,15 +1526,25 @@ void DAG_pose_sort(Object *ob)
|
|||
dag_add_relation(dag, node2, node, 0);
|
||||
|
||||
if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
|
||||
bPoseChannel *par= pchan->parent;
|
||||
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
|
||||
bPoseChannel *parchan;
|
||||
int segcount= 0;
|
||||
|
||||
while(par) {
|
||||
node3= dag_get_node(dag, par);
|
||||
/* exclude tip from chain? */
|
||||
if(!(data->flag & CONSTRAINT_IK_TIP))
|
||||
parchan= pchan->parent;
|
||||
else
|
||||
parchan= pchan;
|
||||
|
||||
/* Walk to the chain's root */
|
||||
while (parchan->parent){
|
||||
segcount++;
|
||||
if(segcount==data->rootbone || segcount>255) break; // 255 is weak
|
||||
|
||||
node3= dag_get_node(dag, parchan);
|
||||
dag_add_relation(dag, node2, node3, 0);
|
||||
|
||||
if(par->bone->flag & BONE_IK_TOPARENT)
|
||||
par= par->parent;
|
||||
else break;
|
||||
parchan= parchan->parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1365,17 +1365,6 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
|
|||
}
|
||||
}
|
||||
|
||||
/* unused */
|
||||
static void lib_link_bone(FileData *fd, ID *id, Bone *bone)
|
||||
{
|
||||
// Bone *curBone;
|
||||
|
||||
// for (curBone=bone->childbase.first; curBone; curBone=curBone->next) {
|
||||
// lib_link_bone(fd, id, curBone);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
|
||||
{
|
||||
bPoseChannel *chan;
|
||||
|
@ -1393,7 +1382,6 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
|
|||
static void lib_link_armature(FileData *fd, Main *main)
|
||||
{
|
||||
bArmature *arm;
|
||||
// Bone *bone;
|
||||
|
||||
arm= main->armature.first;
|
||||
|
||||
|
@ -1401,11 +1389,6 @@ static void lib_link_armature(FileData *fd, Main *main)
|
|||
if(arm->id.flag & LIB_NEEDLINK) {
|
||||
arm->id.flag -= LIB_NEEDLINK;
|
||||
}
|
||||
|
||||
// for (bone=arm->bonebase.first; bone; bone=bone->next) {
|
||||
// lib_link_bone(fd, &arm->id, bone);
|
||||
// }
|
||||
|
||||
arm= arm->id.next;
|
||||
}
|
||||
}
|
||||
|
@ -4905,9 +4888,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||
ob->softflag &= ~OB_SB_ENABLE;
|
||||
}
|
||||
if(ob->pose) {
|
||||
bPoseChannel *pchan;
|
||||
bPoseChannel *pchan, *parchan;
|
||||
bConstraint *con;
|
||||
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
||||
/* 2.38 files can be saved wrong still... */
|
||||
if(pchan->bone==NULL)
|
||||
ob->pose->flag |= POSE_RECALC;
|
||||
|
||||
if (pchan->limitmin[0] == 0.0f && pchan->limitmax[0] == 0.0f) {
|
||||
pchan->limitmin[0]= pchan->limitmin[1]= pchan->limitmin[2]= -180.0f;
|
||||
pchan->limitmax[0]= pchan->limitmax[1]= pchan->limitmax[2]= 180.0f;
|
||||
|
@ -4916,12 +4903,18 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
|||
if(con->type == CONSTRAINT_TYPE_KINEMATIC) {
|
||||
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
|
||||
data->weight = 1.0f;
|
||||
data->orientweight = 0.0f;
|
||||
data->orientweight = 1.0f;
|
||||
data->flag &= ~CONSTRAINT_IK_ROT;
|
||||
|
||||
/* enforce conversion from old IK_TOPARENT to rootbone index */
|
||||
data->rootbone= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* update_pose_etc handles rootbone==-1 */
|
||||
if(!(ob->pose->flag & POSE_RECALC))
|
||||
update_pose_constraint_flags(ob->pose);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ extern void do_soundbuts(unsigned short event);
|
|||
extern void object_panels(void);
|
||||
extern void do_object_panels(unsigned short event);
|
||||
extern void do_constraintbuts(unsigned short event);
|
||||
extern void object_panel_constraint(char *context);
|
||||
|
||||
/* effects */
|
||||
extern void effects_panels(void);
|
||||
|
|
|
@ -133,8 +133,8 @@ enum {
|
|||
POSE_UNUSED3 = 0x0020,
|
||||
POSE_UNUSED4 = 0x0040,
|
||||
POSE_UNUSED5 = 0x0080,
|
||||
POSE_OBMAT = 0x0100,
|
||||
POSE_PARMAT = 0x0200,
|
||||
POSE_HAS_IK = 0x0100,
|
||||
POSE_CHAIN = 0x0200,
|
||||
POSE_DONE = 0x0400,
|
||||
POSE_KEY = 0x1000
|
||||
};
|
||||
|
|
|
@ -112,7 +112,7 @@ typedef struct bArmature {
|
|||
#define BONE_TIPSEL 4
|
||||
/* Used instead of BONE_SELECTED during transform */
|
||||
#define BONE_TRANSFORM 8
|
||||
#define BONE_IK_TOPARENT 16
|
||||
#define BONE_CONNECTED 16
|
||||
/* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */
|
||||
/* hidden Bones when drawing Posechannels */
|
||||
#define BONE_HIDDEN_P 64
|
||||
|
|
|
@ -64,7 +64,8 @@ typedef struct bKinematicConstraint{
|
|||
Object *tar;
|
||||
float tolerance; /* Acceptable distance from target */
|
||||
short iterations; /* Maximum number of iterations to try */
|
||||
short flag; /* Like IK to Tip */
|
||||
short flag; /* Like CONSTRAINT_IK_TIP */
|
||||
int rootbone, pad; /* index to rootbone, if zero go all the way to mother bone */
|
||||
char subtarget[32]; /* String to specify sub-object target */
|
||||
|
||||
float weight; /* Weight of goal in IK tree */
|
||||
|
@ -215,7 +216,6 @@ typedef struct bStretchToConstraint{
|
|||
/* bKinematicConstraint->flag */
|
||||
#define CONSTRAINT_IK_TIP 1
|
||||
#define CONSTRAINT_IK_ROT 2
|
||||
#define CONSTRAINT_IK_TREE 4
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1593,14 +1593,14 @@ static PyObject *Bone_hasIK( BPy_Bone * self )
|
|||
{
|
||||
if( !self->bone ) { //test to see if linked to armature
|
||||
//use python vars
|
||||
if( self->flag & BONE_IK_TOPARENT ) {
|
||||
if( self->flag & BONE_CONNECTED ) {
|
||||
return EXPP_incr_ret_True();
|
||||
} else {
|
||||
return EXPP_incr_ret_False();
|
||||
}
|
||||
} else {
|
||||
//use bone datastruct
|
||||
if( self->bone->flag & BONE_IK_TOPARENT ) {
|
||||
if( self->bone->flag & BONE_CONNECTED ) {
|
||||
return EXPP_incr_ret_True();
|
||||
} else {
|
||||
return EXPP_incr_ret_False();
|
||||
|
|
|
@ -2071,7 +2071,7 @@ static void attach_bone_to_parent_cb(void *bonev, void *arg2_unused)
|
|||
{
|
||||
EditBone *ebone= bonev;
|
||||
|
||||
if (ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) {
|
||||
if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
|
||||
/* Attach this bone to its parent */
|
||||
VECCOPY(ebone->head, ebone->parent->tail);
|
||||
}
|
||||
|
@ -2081,7 +2081,7 @@ static void parnr_to_editbone(EditBone *bone)
|
|||
{
|
||||
if (bone->parNr == -1){
|
||||
bone->parent = NULL;
|
||||
bone->flag &= ~BONE_IK_TOPARENT;
|
||||
bone->flag &= ~BONE_CONNECTED;
|
||||
}
|
||||
else{
|
||||
bone->parent = BLI_findlink(&G.edbo, bone->parNr);
|
||||
|
@ -2255,9 +2255,9 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm)
|
|||
|
||||
MEM_freeN(boneString);
|
||||
|
||||
/* IK to parent flag */
|
||||
/* Connect to parent flag */
|
||||
if (curBone->parent){
|
||||
but=uiDefButBitI(block, TOG, BONE_IK_TOPARENT, B_ARM_RECALCDATA, "IK", bx+300,by,32,18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "IK link to parent");
|
||||
but=uiDefButBitI(block, TOG, BONE_CONNECTED, B_ARM_RECALCDATA, "Con", bx+300,by,32,18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Connect this Bone to Parent");
|
||||
uiButSetFunc(but, attach_bone_to_parent_cb, curBone, NULL);
|
||||
}
|
||||
|
||||
|
@ -2337,7 +2337,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
|
|||
zerolimit = 1;
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG, BONE_IK_NO_XDOF, B_ARM_RECALCDATA, "No X DoF", bx-10,by-60,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable X DoF for IK");
|
||||
uiDefButBitS(block, TOG, BONE_IK_NO_XDOF, B_ARM_RECALCDATA, "Lock X Rot", bx-10,by-60,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable X DoF for IK");
|
||||
if ((pchan->ikflag & BONE_IK_NO_XDOF)==0) {
|
||||
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff X:", bx-10, by-80, 114, 19, &pchan->stiffness[0], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for X axis");
|
||||
uiDefButBitS(block, TOG, BONE_IK_XLIMIT, B_ARM_RECALCDATA, "Limit X", bx-10,by-100,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over X axis");
|
||||
|
@ -2351,7 +2351,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
|
|||
uiBlockEndAlign(block);
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG, BONE_IK_NO_YDOF, B_ARM_RECALCDATA, "No Y DoF", bx+104,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Y DoF for IK");
|
||||
uiDefButBitS(block, TOG, BONE_IK_NO_YDOF, B_ARM_RECALCDATA, "Lock Y Rot", bx+104,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Y DoF for IK");
|
||||
if ((pchan->ikflag & BONE_IK_NO_YDOF)==0) {
|
||||
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Y:", bx+104, by-80, 114, 19, &pchan->stiffness[1], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for Y axis");
|
||||
uiDefButBitS(block, TOG, BONE_IK_YLIMIT, B_ARM_RECALCDATA, "Limit Y", bx+104,by-100,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Y axis");
|
||||
|
@ -2365,7 +2365,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
|
|||
uiBlockEndAlign(block);
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG, BONE_IK_NO_ZDOF, B_ARM_RECALCDATA, "No Z DoF", bx+217,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Z DoF for IK");
|
||||
uiDefButBitS(block, TOG, BONE_IK_NO_ZDOF, B_ARM_RECALCDATA, "Lock Z Rot", bx+217,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Z DoF for IK");
|
||||
if ((pchan->ikflag & BONE_IK_NO_ZDOF)==0) {
|
||||
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Z:", bx+217, by-80, 114, 19, &pchan->stiffness[2], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for Z axis");
|
||||
uiDefButBitS(block, TOG, BONE_IK_ZLIMIT, B_ARM_RECALCDATA, "Limit Z", bx+217,by-100,113,19, &pchan->flag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Z axis");
|
||||
|
@ -3343,6 +3343,7 @@ void editing_panels()
|
|||
}
|
||||
else if(ob->flag & OB_POSEMODE) {
|
||||
editing_panel_pose_bones(ob, arm);
|
||||
object_panel_constraint("Editing");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -423,7 +423,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
|
||||
/* rounded header */
|
||||
rb_col= (con->flag & CONSTRAINT_ACTIVE)?10:-10;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-1, width+30, 22, NULL, 5.0, 0.0,
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-1, width+40, 22, NULL, 5.0, 0.0,
|
||||
(con->flag & CONSTRAINT_EXPAND)?3:15 , rb_col-20, "");
|
||||
|
||||
/* open/close */
|
||||
|
@ -495,7 +495,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
bArmature *arm;
|
||||
|
||||
height = 88;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
|
@ -533,7 +533,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
bArmature *arm;
|
||||
|
||||
height = 66;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
|
@ -563,7 +563,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
bArmature *arm;
|
||||
|
||||
height = 46;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
|
@ -586,33 +586,32 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
bArmature *arm;
|
||||
|
||||
height = 108;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
/* Draw target parameters */
|
||||
uiDefButBitS(block, TOG, CONSTRAINT_IK_ROT, B_CONSTRAINT_TEST, "Rot", *xco, *yco-24,60,19, &data->flag, 0, 0, 0, 0, "Chain follows rotation of target");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
|
||||
uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 19, &data->tar, "Target Object");
|
||||
|
||||
arm = get_armature(data->tar);
|
||||
if (arm)
|
||||
but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
|
||||
but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,19, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
|
||||
else
|
||||
strcpy (data->subtarget, "");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tip", *xco+((width/2)-117), *yco-42, 80, 18, &data->flag, 0, 0, 0, 0, "Include Bone's tip als last element in Chain");
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tip", *xco, *yco-64, 142, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tip als last element in Chain");
|
||||
uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco+142, *yco-64,143,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Tolerance:", *xco+((width/2)-117), *yco-64, 120, 18, &data->tolerance, 0.0001f, 1.0, 0.0, 0.0, "Maximum distance to target after solving");
|
||||
uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+((width/2)+3), *yco-64, 120, 18, &data->iterations, 1, 10000, 0.0, 0.0, "Maximum number of solving iterations");
|
||||
uiBlockEndAlign(block);
|
||||
uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco, *yco-86, 142, 19, &data->weight, 0.01, 1.0, 2, 2, "For Tree-IK: weight of position control for this target");
|
||||
uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "RotW ", *xco+142, *yco-86, 143, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target");
|
||||
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Tolerance:", *xco, *yco-106, 142, 19, &data->tolerance, 0.0001f, 1.0, 0, 0, "Maximum distance to target after solving");
|
||||
uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+142, *yco-106, 143, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations");
|
||||
|
||||
uiDefButBitS(block, TOG, CONSTRAINT_IK_TREE, B_CONSTRAINT_TEST, "Tree IK", *xco+((width/2)-117), *yco-86,120,18, &data->flag, 0, 0, 0, 0, "IK chain becomes tree, when it shares Root with other Chains");
|
||||
uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "Weight ", *xco+((width/2)+3), *yco-86, 120, 18, &data->weight, 0.0, 1.0, 0.0, 0.0, "Weight of position control for this target");
|
||||
|
||||
uiDefButBitS(block, TOG, CONSTRAINT_IK_ROT, B_CONSTRAINT_TEST, "Orientation", *xco+((width/2)-117), *yco-108,120,18, &data->flag, 0, 0, 0, 0, "Follow orientation of target");
|
||||
uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "Weight ", *xco+((width/2)+3), *yco-108, 120, 18, &data->orientweight, 0.0, 1.0, 0.0, 0.0, "Weight of orientation control for this target");
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_TRACKTO:
|
||||
|
@ -621,7 +620,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
bArmature *arm;
|
||||
|
||||
height = 66;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
|
@ -662,7 +661,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
bLockTrackConstraint *data = con->data;
|
||||
bArmature *arm;
|
||||
height = 66;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
|
@ -703,7 +702,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
bFollowPathConstraint *data = con->data;
|
||||
|
||||
height = 66;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
|
@ -742,7 +741,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
bArmature *arm;
|
||||
|
||||
height = 105;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
|
@ -786,7 +785,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
|||
case CONSTRAINT_TYPE_NULL:
|
||||
{
|
||||
height = 17;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
}
|
||||
break;
|
||||
|
@ -973,7 +972,7 @@ void do_constraintbuts(unsigned short event)
|
|||
allqueue (REDRAWBUTSOBJECT, 0);
|
||||
}
|
||||
|
||||
static void object_panel_constraint(void)
|
||||
void object_panel_constraint(char *context)
|
||||
{
|
||||
uiBlock *block;
|
||||
Object *ob= OBACT;
|
||||
|
@ -983,7 +982,7 @@ static void object_panel_constraint(void)
|
|||
char str[64];
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "object_panel_constraint", UI_EMBOSS, UI_HELV, curarea->win);
|
||||
if(uiNewPanel(curarea, block, "Constraints", "Object", 640, 0, 318, 204)==0) return;
|
||||
if(uiNewPanel(curarea, block, "Constraints", context, 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 */
|
||||
|
@ -1758,7 +1757,7 @@ void object_panels()
|
|||
|
||||
object_panel_anim(ob);
|
||||
object_panel_draw(ob);
|
||||
object_panel_constraint();
|
||||
object_panel_constraint("Object");
|
||||
if(ob->type==OB_MESH) {
|
||||
object_panel_effects(ob);
|
||||
}
|
||||
|
|
|
@ -333,8 +333,8 @@ static void draw_bone_solid_octahedral(void)
|
|||
|
||||
static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id)
|
||||
{
|
||||
/* Draw root point if we have no IK parent */
|
||||
if (!(boneflag & BONE_IK_TOPARENT)){
|
||||
/* Draw root point if we are not connected */
|
||||
if (!(boneflag & BONE_CONNECTED)){
|
||||
if (id != -1)
|
||||
glLoadName (id | BONESEL_ROOT);
|
||||
|
||||
|
@ -413,7 +413,7 @@ static void draw_sphere_bone_dist(float smat[][4], float imat[][4], int boneflag
|
|||
length= ebone->length;
|
||||
tail= ebone->rad_tail;
|
||||
dist= ebone->dist;
|
||||
if (ebone->parent && (ebone->flag & BONE_IK_TOPARENT))
|
||||
if (ebone->parent && (ebone->flag & BONE_CONNECTED))
|
||||
head= ebone->parent->rad_tail;
|
||||
else
|
||||
head= ebone->rad_head;
|
||||
|
@ -424,7 +424,7 @@ static void draw_sphere_bone_dist(float smat[][4], float imat[][4], int boneflag
|
|||
length= pchan->bone->length;
|
||||
tail= pchan->bone->rad_tail;
|
||||
dist= pchan->bone->dist;
|
||||
if (pchan->parent && (pchan->bone->flag & BONE_IK_TOPARENT))
|
||||
if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
|
||||
head= pchan->parent->bone->rad_tail;
|
||||
else
|
||||
head= pchan->bone->rad_head;
|
||||
|
@ -522,7 +522,7 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag,
|
|||
|
||||
length= ebone->length;
|
||||
tail= ebone->rad_tail;
|
||||
if (ebone->parent && (boneflag & BONE_IK_TOPARENT))
|
||||
if (ebone->parent && (boneflag & BONE_CONNECTED))
|
||||
head= ebone->parent->rad_tail;
|
||||
else
|
||||
head= ebone->rad_head;
|
||||
|
@ -532,7 +532,7 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag,
|
|||
else {
|
||||
length= pchan->bone->length;
|
||||
tail= pchan->bone->rad_tail;
|
||||
if (pchan->parent && (boneflag & BONE_IK_TOPARENT))
|
||||
if (pchan->parent && (boneflag & BONE_CONNECTED))
|
||||
head= pchan->parent->bone->rad_tail;
|
||||
else
|
||||
head= pchan->bone->rad_head;
|
||||
|
@ -552,8 +552,8 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag,
|
|||
else BIF_ThemeColor(TH_WIRE);
|
||||
}
|
||||
|
||||
/* Draw root point if we have no IK parent */
|
||||
if (!(boneflag & BONE_IK_TOPARENT)){
|
||||
/* Draw root point if we are not connected */
|
||||
if (!(boneflag & BONE_CONNECTED)){
|
||||
if (id != -1)
|
||||
glLoadName (id | BONESEL_ROOT);
|
||||
|
||||
|
@ -636,7 +636,7 @@ static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, u
|
|||
if(ebone) {
|
||||
length= ebone->length;
|
||||
tail= ebone->rad_tail;
|
||||
if (ebone->parent && (boneflag & BONE_IK_TOPARENT))
|
||||
if (ebone->parent && (boneflag & BONE_CONNECTED))
|
||||
head= ebone->parent->rad_tail;
|
||||
else
|
||||
head= ebone->rad_head;
|
||||
|
@ -644,7 +644,7 @@ static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, u
|
|||
else {
|
||||
length= pchan->bone->length;
|
||||
tail= pchan->bone->rad_tail;
|
||||
if (pchan->parent && (boneflag & BONE_IK_TOPARENT))
|
||||
if (pchan->parent && (boneflag & BONE_CONNECTED))
|
||||
head= pchan->parent->bone->rad_tail;
|
||||
else
|
||||
head= pchan->bone->rad_head;
|
||||
|
@ -679,8 +679,8 @@ static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, u
|
|||
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)){
|
||||
/* Draw root point if we are not connected */
|
||||
if (!(boneflag & BONE_CONNECTED)){
|
||||
if (id != -1)
|
||||
glLoadName (id | BONESEL_ROOT);
|
||||
gluSphere( qobj, head, 16, 10);
|
||||
|
@ -788,8 +788,8 @@ static void draw_line_bone(int armflag, int boneflag, int constflag, unsigned in
|
|||
BIF_ThemeColor(TH_WIRE);
|
||||
}
|
||||
|
||||
/* Draw root point if we have no IK parent */
|
||||
if (!(boneflag & BONE_IK_TOPARENT)){
|
||||
/* Draw root point if we are not connected */
|
||||
if (!(boneflag & BONE_CONNECTED)){
|
||||
if (G.f & G_PICKSEL) { // no bitmap in selection mode, crashes 3d cards...
|
||||
glLoadName (id | BONESEL_ROOT);
|
||||
glBegin(GL_POINTS);
|
||||
|
@ -839,8 +839,8 @@ static void draw_line_bone(int armflag, int boneflag, int constflag, unsigned in
|
|||
|
||||
glLineWidth(2.0);
|
||||
|
||||
/* Draw root point if we have no IK parent */
|
||||
if (!(boneflag & BONE_IK_TOPARENT)){
|
||||
/* Draw root point if we are not connected */
|
||||
if (!(boneflag & BONE_CONNECTED)){
|
||||
if ((G.f & G_PICKSEL)==0) { // no bitmap in selection mode, crashes 3d cards...
|
||||
if(armflag & ARM_EDITMODE) {
|
||||
if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
|
||||
|
@ -1064,6 +1064,43 @@ static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned
|
|||
}
|
||||
}
|
||||
|
||||
static void pchan_draw_IK_root_lines(bPoseChannel *pchan)
|
||||
{
|
||||
bConstraint *con;
|
||||
bPoseChannel *parchan;
|
||||
|
||||
for(con= pchan->constraints.first; con; con= con->next) {
|
||||
if(con->type == CONSTRAINT_TYPE_KINEMATIC) {
|
||||
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
|
||||
int segcount= 0;
|
||||
|
||||
setlinestyle(3);
|
||||
glBegin(GL_LINES);
|
||||
|
||||
/* exclude tip from chain? */
|
||||
if(!(data->flag & CONSTRAINT_IK_TIP))
|
||||
parchan= pchan->parent;
|
||||
else
|
||||
parchan= pchan;
|
||||
|
||||
glVertex3fv(parchan->pose_tail);
|
||||
|
||||
/* Find the chain's root */
|
||||
while (parchan->parent){
|
||||
segcount++;
|
||||
if(segcount==data->rootbone || segcount>255) break; // 255 is weak
|
||||
parchan= parchan->parent;
|
||||
}
|
||||
if(parchan)
|
||||
glVertex3fv(parchan->pose_head);
|
||||
|
||||
glEnd();
|
||||
setlinestyle(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* assumes object is Armature with pose */
|
||||
static void draw_pose_channels(Base *base, int dt)
|
||||
{
|
||||
|
@ -1127,7 +1164,7 @@ static void draw_pose_channels(Base *base, int dt)
|
|||
/* catch exception for bone with hidden parent */
|
||||
flag= bone->flag;
|
||||
if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P))
|
||||
flag &= ~BONE_IK_TOPARENT;
|
||||
flag &= ~BONE_CONNECTED;
|
||||
|
||||
if(arm->drawtype==ARM_ENVELOPE)
|
||||
draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
|
||||
|
@ -1161,19 +1198,31 @@ 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_P)) {
|
||||
|
||||
// Draw a line from our root to the parent's tip
|
||||
if (do_dashed && bone->parent && !(bone->flag & BONE_IK_TOPARENT) ){
|
||||
if (arm->flag & ARM_POSEMODE) {
|
||||
glLoadName (index & 0xFFFF); // object tag, for bordersel optim
|
||||
BIF_ThemeColor(TH_WIRE);
|
||||
|
||||
if (do_dashed && bone->parent) {
|
||||
// Draw a line from our root to the parent's tip
|
||||
if(!(bone->flag & BONE_CONNECTED) ){
|
||||
if (arm->flag & ARM_POSEMODE) {
|
||||
glLoadName (index & 0xFFFF); // object tag, for bordersel optim
|
||||
BIF_ThemeColor(TH_WIRE);
|
||||
}
|
||||
setlinestyle(3);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(pchan->pose_head);
|
||||
glVertex3fv(pchan->parent->pose_tail);
|
||||
glEnd();
|
||||
setlinestyle(0);
|
||||
}
|
||||
// Draw a line to IK root bone
|
||||
if(arm->flag & ARM_POSEMODE) {
|
||||
if(pchan->constflag & PCHAN_HAS_IK) {
|
||||
if(bone->flag & BONE_SELECTED) {
|
||||
glLoadName (index & 0xFFFF);
|
||||
glColor3ub(200, 200, 50); // add theme!
|
||||
pchan_draw_IK_root_lines(pchan);
|
||||
}
|
||||
}
|
||||
}
|
||||
setlinestyle(3);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(pchan->pose_head);
|
||||
glVertex3fv(pchan->parent->pose_tail);
|
||||
glEnd();
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
if(arm->drawtype!=ARM_ENVELOPE) {
|
||||
|
@ -1184,7 +1233,7 @@ static void draw_pose_channels(Base *base, int dt)
|
|||
/* catch exception for bone with hidden parent */
|
||||
flag= bone->flag;
|
||||
if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P))
|
||||
flag &= ~BONE_IK_TOPARENT;
|
||||
flag &= ~BONE_CONNECTED;
|
||||
|
||||
/* extra draw service for pose mode */
|
||||
constflag= pchan->constflag;
|
||||
|
@ -1321,7 +1370,7 @@ static void draw_ebones(Object *ob, int dt)
|
|||
/* catch exception for bone with hidden parent */
|
||||
flag= eBone->flag;
|
||||
if(eBone->parent && (eBone->parent->flag & BONE_HIDDEN_A))
|
||||
flag &= ~BONE_IK_TOPARENT;
|
||||
flag &= ~BONE_CONNECTED;
|
||||
|
||||
if(arm->drawtype==ARM_ENVELOPE)
|
||||
draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
|
||||
|
@ -1338,6 +1387,7 @@ static void draw_ebones(Object *ob, int dt)
|
|||
|
||||
/* if wire over solid, set offset */
|
||||
index= -1;
|
||||
glLoadName(-1);
|
||||
if(arm->drawtype==ARM_LINE) {
|
||||
if(G.f & G_PICKSEL)
|
||||
index= 0;
|
||||
|
@ -1353,7 +1403,7 @@ static void draw_ebones(Object *ob, int dt)
|
|||
/* catch exception for bone with hidden parent */
|
||||
flag= eBone->flag;
|
||||
if(eBone->parent && (eBone->parent->flag & BONE_HIDDEN_A))
|
||||
flag &= ~BONE_IK_TOPARENT;
|
||||
flag &= ~BONE_CONNECTED;
|
||||
|
||||
if(arm->drawtype==ARM_ENVELOPE) {
|
||||
if(dt<OB_SOLID)
|
||||
|
|
|
@ -1669,13 +1669,13 @@ void do_viewbuts(unsigned short event)
|
|||
if (ebone) {
|
||||
ebone->roll= M_PI*ob_eul[0]/180.0;
|
||||
// Update our parent
|
||||
if (ebone->parent && ebone->flag & BONE_IK_TOPARENT){
|
||||
if (ebone->parent && ebone->flag & BONE_CONNECTED){
|
||||
VECCOPY (ebone->parent->tail, ebone->head);
|
||||
}
|
||||
|
||||
// Update our children if necessary
|
||||
for (child = G.edbo.first; child; child=child->next){
|
||||
if (child->parent == ebone && (child->flag & BONE_IK_TOPARENT)){
|
||||
if (child->parent == ebone && (child->flag & BONE_CONNECTED)){
|
||||
VECCOPY (child->head, ebone->tail);
|
||||
}
|
||||
}
|
||||
|
@ -1687,13 +1687,13 @@ void do_viewbuts(unsigned short event)
|
|||
eboflip->tail[0]= -ebone->tail[0];
|
||||
|
||||
// Update our parent
|
||||
if (eboflip->parent && eboflip->flag & BONE_IK_TOPARENT){
|
||||
if (eboflip->parent && eboflip->flag & BONE_CONNECTED){
|
||||
VECCOPY (eboflip->parent->tail, eboflip->head);
|
||||
}
|
||||
|
||||
// Update our children if necessary
|
||||
for (child = G.edbo.first; child; child=child->next){
|
||||
if (child->parent == eboflip && (child->flag & BONE_IK_TOPARENT)){
|
||||
if (child->parent == eboflip && (child->flag & BONE_CONNECTED)){
|
||||
VECCOPY (child->head, eboflip->tail);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -589,8 +589,8 @@ void countall()
|
|||
for (ebo=G.edbo.first;ebo;ebo=ebo->next){
|
||||
G.totbone++;
|
||||
|
||||
/* Sync selection to parent for ik children */
|
||||
if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
|
||||
/* Sync selection to parent for connected children */
|
||||
if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
|
||||
G.totvert--;
|
||||
if (ebo->parent->flag & BONE_TIPSEL)
|
||||
ebo->flag |= BONE_ROOTSEL;
|
||||
|
@ -610,8 +610,8 @@ void countall()
|
|||
|
||||
if(ebo->flag & BONE_SELECTED) G.totbonesel++;
|
||||
|
||||
// If this is an IK child and it's parent is being moved, remove our root
|
||||
if ((ebo->flag & BONE_IK_TOPARENT)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL)){
|
||||
// If this is a connected child and it's parent is being moved, remove our root
|
||||
if ((ebo->flag & BONE_CONNECTED)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL)){
|
||||
G.totvertsel--;
|
||||
}
|
||||
|
||||
|
@ -752,7 +752,7 @@ static void special_transvert_update(void)
|
|||
/* Ensure all bones are correctly adjusted */
|
||||
for (ebo=G.edbo.first; ebo; ebo=ebo->next){
|
||||
|
||||
if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
|
||||
if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
|
||||
/* If this bone has a parent tip that has been moved */
|
||||
if (ebo->parent->flag & BONE_TIPSEL){
|
||||
VECCOPY (ebo->head, ebo->parent->tail);
|
||||
|
@ -880,9 +880,9 @@ static void make_trans_verts(float *min, float *max, int mode)
|
|||
tottrans++;
|
||||
}
|
||||
|
||||
/* Only add the root if there is no selected IK parent */
|
||||
/* Only add the root if there is no connection */
|
||||
if (ebo->flag & BONE_ROOTSEL){
|
||||
if (!(ebo->parent && (ebo->flag & BONE_IK_TOPARENT) && ebo->parent->flag & BONE_TIPSEL)){
|
||||
if (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && ebo->parent->flag & BONE_TIPSEL)){
|
||||
VECCOPY (tv->oldloc, ebo->head);
|
||||
tv->loc= ebo->head;
|
||||
tv->nor= NULL;
|
||||
|
|
|
@ -132,7 +132,7 @@ static void make_boneList(ListBase* list, ListBase *bones, EditBone *parent)
|
|||
/* fix selection flags */
|
||||
if(eBone->flag & BONE_SELECTED) {
|
||||
eBone->flag |= BONE_TIPSEL;
|
||||
if(eBone->parent && (eBone->flag & BONE_IK_TOPARENT))
|
||||
if(eBone->parent && (eBone->flag & BONE_CONNECTED))
|
||||
eBone->parent->flag |= BONE_TIPSEL;
|
||||
else
|
||||
eBone->flag |= BONE_ROOTSEL;
|
||||
|
@ -579,7 +579,7 @@ static void selectconnected_posebonechildren (Object *ob, Bone *bone)
|
|||
{
|
||||
Bone *curBone;
|
||||
|
||||
if (!(bone->flag & BONE_IK_TOPARENT))
|
||||
if (!(bone->flag & BONE_CONNECTED))
|
||||
return;
|
||||
|
||||
select_actionchannel_by_name (ob->action, bone->name, !(G.qual & LR_SHIFTKEY));
|
||||
|
@ -618,7 +618,7 @@ void selectconnected_posearmature(void)
|
|||
else
|
||||
curBone->flag |= BONE_SELECTED;
|
||||
|
||||
if (curBone->flag & BONE_IK_TOPARENT)
|
||||
if (curBone->flag & BONE_CONNECTED)
|
||||
next=curBone->parent;
|
||||
else
|
||||
next=NULL;
|
||||
|
@ -701,7 +701,7 @@ void selectconnected_armature(void)
|
|||
curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
|
||||
}
|
||||
|
||||
if (curBone->flag & BONE_IK_TOPARENT)
|
||||
if (curBone->flag & BONE_CONNECTED)
|
||||
next=curBone->parent;
|
||||
else
|
||||
next=NULL;
|
||||
|
@ -712,7 +712,7 @@ void selectconnected_armature(void)
|
|||
for (curBone=G.edbo.first; curBone; curBone=next){
|
||||
next = curBone->next;
|
||||
if (curBone->parent == bone){
|
||||
if (curBone->flag & BONE_IK_TOPARENT){
|
||||
if (curBone->flag & BONE_CONNECTED){
|
||||
if (G.qual & LR_SHIFTKEY)
|
||||
curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
|
||||
else
|
||||
|
@ -833,7 +833,7 @@ static void delete_bone(EditBone* exBone)
|
|||
for (curBone=G.edbo.first;curBone;curBone=curBone->next){
|
||||
if (curBone->parent==exBone){
|
||||
curBone->parent=exBone->parent;
|
||||
curBone->flag &= ~BONE_IK_TOPARENT;
|
||||
curBone->flag &= ~BONE_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -907,12 +907,12 @@ void mouse_armature(void)
|
|||
deselectall_armature(0);
|
||||
}
|
||||
|
||||
/* by definition the non-root non-IK bones have no root point drawn,
|
||||
/* by definition the non-root non-connected bones have no root point drawn,
|
||||
so a root selection needs to be delivered to the parent tip,
|
||||
countall() (bad location) flushes these flags */
|
||||
|
||||
if(selmask & BONE_SELECTED) {
|
||||
if(nearBone->parent && (nearBone->flag & BONE_IK_TOPARENT)) {
|
||||
if(nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
|
||||
/* click in a chain */
|
||||
if(G.qual & LR_SHIFTKEY) {
|
||||
/* hold shift inverts this bone's selection */
|
||||
|
@ -1280,7 +1280,7 @@ void addvert_armature(void)
|
|||
VECCOPY(newbone->head, ebone->tail);
|
||||
|
||||
newbone->parent= ebone;
|
||||
newbone->flag |= BONE_IK_TOPARENT;
|
||||
newbone->flag |= BONE_CONNECTED;
|
||||
}
|
||||
|
||||
curs= give_cursor();
|
||||
|
@ -1368,7 +1368,7 @@ void adduplicate_armature(void)
|
|||
*/
|
||||
else {
|
||||
eBone->parent=(EditBone*) curBone->parent;
|
||||
eBone->flag &= ~BONE_IK_TOPARENT;
|
||||
eBone->flag &= ~BONE_CONNECTED;
|
||||
}
|
||||
|
||||
/* Lets try to fix any constraint subtargets that might
|
||||
|
@ -1473,10 +1473,20 @@ void make_bone_parent(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
if(selbone==NULL) error("Need one active and one selected bone");
|
||||
if(selbone==NULL) {
|
||||
/* we make sure bone is connected */
|
||||
if(val==1 && actbone->parent) {
|
||||
actbone->flag |= BONE_CONNECTED;
|
||||
VECCOPY(actbone->head, actbone->parent->tail);
|
||||
countall(); // checks selection
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
BIF_undo_push("Connect to Parent");
|
||||
}
|
||||
else error("Need one active and one selected bone");
|
||||
}
|
||||
else {
|
||||
/* if selbone had a parent we clear parent tip */
|
||||
if(selbone->parent && (selbone->flag & BONE_IK_TOPARENT))
|
||||
if(selbone->parent && (selbone->flag & BONE_CONNECTED))
|
||||
selbone->parent->flag &= ~(BONE_TIPSEL);
|
||||
|
||||
selbone->parent= actbone;
|
||||
|
@ -1485,12 +1495,12 @@ void make_bone_parent(void)
|
|||
for(ebone= actbone->parent; ebone; ebone= ebone->parent) {
|
||||
if(ebone->parent==selbone) {
|
||||
ebone->parent= NULL;
|
||||
ebone->flag &= ~BONE_IK_TOPARENT;
|
||||
ebone->flag &= ~BONE_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
if(val==1) { // connected
|
||||
selbone->flag |= BONE_IK_TOPARENT;
|
||||
selbone->flag |= BONE_CONNECTED;
|
||||
VecSubf(offset, actbone->tail, selbone->head);
|
||||
|
||||
VECCOPY(selbone->head, actbone->tail);
|
||||
|
@ -1509,16 +1519,16 @@ void make_bone_parent(void)
|
|||
}
|
||||
}
|
||||
else {
|
||||
selbone->flag &= ~BONE_IK_TOPARENT;
|
||||
selbone->flag &= ~BONE_CONNECTED;
|
||||
}
|
||||
|
||||
countall(); // checks selection
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWOOPS, 0);
|
||||
BIF_undo_push("Make Parent");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void clear_bone_parent(void)
|
||||
|
@ -1526,7 +1536,7 @@ void clear_bone_parent(void)
|
|||
EditBone *ebone;
|
||||
short val;
|
||||
|
||||
val= pupmenu("Clear Parent%t|Clear Parent%x1|Disconnect IK%x2");
|
||||
val= pupmenu("Clear Parent%t|Clear Parent%x1|Disconnect Bone%x2");
|
||||
|
||||
if(val<1) return;
|
||||
for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
|
||||
|
@ -1536,8 +1546,7 @@ void clear_bone_parent(void)
|
|||
ebone->parent->flag &= ~(BONE_TIPSEL);
|
||||
|
||||
if(val==1) ebone->parent= NULL;
|
||||
ebone->flag &= ~BONE_IK_TOPARENT;
|
||||
|
||||
ebone->flag &= ~BONE_CONNECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1545,6 +1554,7 @@ void clear_bone_parent(void)
|
|||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWOOPS, 0);
|
||||
BIF_undo_push("Clear Parent");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1600,7 +1610,7 @@ void extrude_armature(int forked)
|
|||
/* 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 && (ebone->flag & BONE_CONNECTED)) {
|
||||
if(ebone->parent->flag & BONE_TIPSEL)
|
||||
ebone->flag &= ~BONE_ROOTSEL;
|
||||
}
|
||||
|
@ -1674,7 +1684,7 @@ void extrude_armature(int forked)
|
|||
newbone->segments= 1;
|
||||
newbone->boneclass= ebone->boneclass;
|
||||
|
||||
newbone->flag |= BONE_IK_TOPARENT;
|
||||
if(newbone->parent) newbone->flag |= BONE_CONNECTED;
|
||||
|
||||
strcpy (newbone->name, ebone->name);
|
||||
|
||||
|
@ -1934,14 +1944,14 @@ int ik_chain_looper(Object *ob, Bone *bone, void *data,
|
|||
for (curBone = bone; curBone; curBone=curBone->parent) {
|
||||
if (!curBone->parent)
|
||||
break;
|
||||
else if (!(curBone->flag & BONE_IK_TOPARENT))
|
||||
else if (!(curBone->flag & BONE_CONNECTED))
|
||||
break;
|
||||
count += bone_func(ob, curBone->parent, data);
|
||||
}
|
||||
|
||||
/* The children */
|
||||
for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
|
||||
if (curBone->flag & BONE_IK_TOPARENT) {
|
||||
if (curBone->flag & BONE_CONNECTED) {
|
||||
count += bone_func(ob, curBone, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,22 +116,20 @@ ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
|
|||
/* if object in posemode, active bone constraints, else object constraints */
|
||||
ListBase *get_active_constraints(Object *ob)
|
||||
{
|
||||
ListBase *list;
|
||||
|
||||
if (!ob)
|
||||
return NULL;
|
||||
|
||||
list = &ob->constraints;
|
||||
|
||||
if (ob->flag & OB_POSEMODE) {
|
||||
bPoseChannel *pchan;
|
||||
|
||||
pchan = get_active_posechannel(ob);
|
||||
if (pchan)
|
||||
list = &pchan->constraints;
|
||||
return &pchan->constraints;
|
||||
}
|
||||
else
|
||||
return &ob->constraints;
|
||||
|
||||
return list;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* single constraint */
|
||||
|
|
|
@ -1294,7 +1294,7 @@ static int tree_element_active_ebone(TreeElement *te, TreeStoreElem *tselem, int
|
|||
|
||||
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(ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag |= BONE_TIPSEL;
|
||||
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWOOPS, 0);
|
||||
|
|
|
@ -261,14 +261,21 @@ void pose_add_IK(void)
|
|||
bPoseChannel *pchan= pchanact;
|
||||
while(pchan) {
|
||||
if(pchan==pchansel) break;
|
||||
if(pchan->bone->flag & BONE_IK_TOPARENT)
|
||||
pchan= pchan->parent;
|
||||
else pchan= NULL;
|
||||
pchan= pchan->parent;
|
||||
}
|
||||
if(pchan) {
|
||||
error("IK target should not be in the IK chain itself");
|
||||
error("IK root cannot be linked to IK tip");
|
||||
return;
|
||||
}
|
||||
pchan= pchansel;
|
||||
while(pchan) {
|
||||
if(pchan==pchanact) break;
|
||||
pchan= pchan->parent;
|
||||
}
|
||||
if(pchan) {
|
||||
error("IK tip cannot be linked to IK root");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
|
||||
|
|
|
@ -382,8 +382,8 @@ void count_bone_select(TransInfo *t, ListBase *lb, int do_it)
|
|||
do_next= do_it;
|
||||
if(do_it) {
|
||||
if (bone->flag & BONE_SELECTED) {
|
||||
/* We don't let IK children get "grabbed" */
|
||||
if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
|
||||
/* We don't let connected children get "grabbed" */
|
||||
if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_CONNECTED)==0 ) {
|
||||
bone->flag |= BONE_TRANSFORM;
|
||||
t->total++;
|
||||
do_next= 0; // no transform on children if one parent bone is selected
|
||||
|
@ -402,8 +402,8 @@ static int add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tra
|
|||
|
||||
if(bone) {
|
||||
if (bone->flag & BONE_TRANSFORM) {
|
||||
/* We don't let IK children get "grabbed" */
|
||||
if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
|
||||
/* We don't let connected children get "grabbed" */
|
||||
if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_CONNECTED)==0 ) {
|
||||
|
||||
VECCOPY(vec, pchan->pose_mat[3]);
|
||||
VECCOPY(td->center, vec);
|
||||
|
|
|
@ -183,7 +183,7 @@ void recalcData(TransInfo *t)
|
|||
/* Ensure all bones are correctly adjusted */
|
||||
for (ebo=G.edbo.first; ebo; ebo=ebo->next){
|
||||
|
||||
if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
|
||||
if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
|
||||
/* If this bone has a parent tip that has been moved */
|
||||
if (ebo->parent->flag & BONE_TIPSEL){
|
||||
VECCOPY (ebo->head, ebo->parent->tail);
|
||||
|
|
|
@ -219,8 +219,8 @@ int calc_manipulator_stats(ScrArea *sa)
|
|||
EditBone *ebo;
|
||||
for (ebo=G.edbo.first;ebo;ebo=ebo->next){
|
||||
|
||||
// If this is an IK child and it's parent is being moved, don't count as selected
|
||||
if ((ebo->flag & BONE_IK_TOPARENT)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL));
|
||||
// If this is a connected child and it's parent is being moved, don't count as selected
|
||||
if ((ebo->flag & BONE_CONNECTED)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL));
|
||||
else {
|
||||
if (ebo->flag & BONE_TIPSEL) {
|
||||
calc_tw_center(ebo->tail);
|
||||
|
|
Loading…
Reference in New Issue