static void cyclic_offs_bone(Object *ob, bPose *pose, bActionStrip *strip, float time) { /* only called when strip has cyclic, so >= 1.0f works... */ if(time >= 1.0f) { bActionChannel *achan= get_action_channel(strip->act, strip->offs_bone); if(achan && achan->ipo) { IpoCurve *icu= NULL; Bone *bone; float min[3]={0.0f, 0.0f, 0.0f}, max[3]={0.0f, 0.0f, 0.0f}; int index=0, foundvert= 0; /* calculate the min/max */ for (icu=achan->ipo->curve.first; icu; icu=icu->next) { if(icu->totvert>1) { if(icu->adrcode==AC_LOC_X) index= 0; else if(icu->adrcode==AC_LOC_Y) index= 1; else if(icu->adrcode==AC_LOC_Z) index= 2; else continue; foundvert= 1; min[index]= icu->bezt[0].vec[1][1]; max[index]= icu->bezt[icu->totvert-1].vec[1][1]; } } if(foundvert) { /* bring it into armature space */ sub_v3_v3v3(min, max, min); bone= get_named_bone(ob->data, strip->offs_bone); /* weak */ if(bone) { mul_mat3_m4_v3(bone->arm_mat, min); /* dominant motion, cyclic_offset was cleared in rest_pose */ if (strip->flag & (ACTSTRIP_CYCLIC_USEX | ACTSTRIP_CYCLIC_USEY | ACTSTRIP_CYCLIC_USEZ)) { if (strip->flag & ACTSTRIP_CYCLIC_USEX) pose->cyclic_offset[0]= time*min[0]; if (strip->flag & ACTSTRIP_CYCLIC_USEY) pose->cyclic_offset[1]= time*min[1]; if (strip->flag & ACTSTRIP_CYCLIC_USEZ) pose->cyclic_offset[2]= time*min[2]; } else { if( fabs(min[0]) >= fabs(min[1]) && fabs(min[0]) >= fabs(min[2])) pose->cyclic_offset[0]= time*min[0]; else if( fabs(min[1]) >= fabs(min[0]) && fabs(min[1]) >= fabs(min[2])) pose->cyclic_offset[1]= time*min[1]; else pose->cyclic_offset[2]= time*min[2]; } } } } } }
/* checks validity of object pointers, and NULLs, * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag */ static void test_constraints (Object *owner, const char substring[]) { bConstraint *curcon; ListBase *conlist= NULL; int type; if (owner==NULL) return; /* Check parents */ if (strlen(substring)) { switch (owner->type) { case OB_ARMATURE: type = CONSTRAINT_OBTYPE_BONE; break; default: type = CONSTRAINT_OBTYPE_OBJECT; break; } } else type = CONSTRAINT_OBTYPE_OBJECT; /* Get the constraint list for this object */ switch (type) { case CONSTRAINT_OBTYPE_OBJECT: conlist = &owner->constraints; break; case CONSTRAINT_OBTYPE_BONE: { Bone *bone; bPoseChannel *chan; bone = get_named_bone( ((bArmature *)owner->data), substring ); chan = get_pose_channel(owner->pose, substring); if (bone && chan) { conlist = &chan->constraints; } } break; } /* Check all constraints - is constraint valid? */ if (conlist) { for (curcon = conlist->first; curcon; curcon=curcon->next) { bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; /* clear disabled-flag first */ curcon->flag &= ~CONSTRAINT_DISABLE; if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) { bKinematicConstraint *data = curcon->data; /* bad: we need a separate set of checks here as poletarget is * optional... otherwise poletarget must exist too or else * the constraint is deemed invalid */ /* default IK check ... */ if (exist_object(data->tar) == 0) { data->tar = NULL; curcon->flag |= CONSTRAINT_DISABLE; } else if (data->tar == owner) { if (!get_named_bone(get_armature(owner), data->subtarget)) { curcon->flag |= CONSTRAINT_DISABLE; } } if (data->poletar) { if (exist_object(data->poletar) == 0) { data->poletar = NULL; curcon->flag |= CONSTRAINT_DISABLE; } else if (data->poletar == owner) { if (!get_named_bone(get_armature(owner), data->polesubtarget)) { curcon->flag |= CONSTRAINT_DISABLE; } } } /* ... can be overwritten here */ BIK_test_constraint(owner, curcon); /* targets have already been checked for this */ continue; } else if (curcon->type == CONSTRAINT_TYPE_ACTION) { bActionConstraint *data = curcon->data; /* validate action */ if (data->act == NULL) curcon->flag |= CONSTRAINT_DISABLE; } else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) { bFollowPathConstraint *data = curcon->data; /* don't allow track/up axes to be the same */ if (data->upflag==data->trackflag) curcon->flag |= CONSTRAINT_DISABLE; if (data->upflag+3==data->trackflag) curcon->flag |= CONSTRAINT_DISABLE; } else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) { bTrackToConstraint *data = curcon->data; /* don't allow track/up axes to be the same */ if (data->reserved2==data->reserved1) curcon->flag |= CONSTRAINT_DISABLE; if (data->reserved2+3==data->reserved1) curcon->flag |= CONSTRAINT_DISABLE; } else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) { bLockTrackConstraint *data = curcon->data; if (data->lockflag==data->trackflag) curcon->flag |= CONSTRAINT_DISABLE; if (data->lockflag+3==data->trackflag) curcon->flag |= CONSTRAINT_DISABLE; } /* Check targets for constraints */ if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(curcon, &targets); /* disable and clear constraints targets that are incorrect */ for (ct= targets.first; ct; ct= ct->next) { /* general validity checks (for those constraints that need this) */ if (exist_object(ct->tar) == 0) { ct->tar = NULL; curcon->flag |= CONSTRAINT_DISABLE; } else if (ct->tar == owner) { if (!get_named_bone(get_armature(owner), ct->subtarget)) { curcon->flag |= CONSTRAINT_DISABLE; } } /* target checks for specific constraints */ if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) { if (ct->tar) { if (ct->tar->type != OB_CURVE) { ct->tar= NULL; curcon->flag |= CONSTRAINT_DISABLE; } else { Curve *cu= ct->tar->data; /* auto-set 'Path' setting on curve so this works */ cu->flag |= CU_PATH; } } } } /* free any temporary targets */ if (cti->flush_constraint_targets) cti->flush_constraint_targets(curcon, &targets, 0); } } } }