diff options
author | Joshua Leung <aligorith@gmail.com> | 2007-12-15 10:35:16 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2007-12-15 10:35:16 +0300 |
commit | faf638238dc5147fa3b9c5cc4999bda907acd6f7 (patch) | |
tree | 9d91470d9e5d233524c2aff5df87067a642d4ffe /source/blender | |
parent | b71d55b055ec0bd4be54b5d127eaab9d87e89b37 (diff) |
== Auto-IK ==
-- Peach request (from wiki feature request list) --
When translating a bone using Auto-IK, you can now use the ScrollWheel on the Mouse or the Page Up/Down keys to adjust the chain length.
Notes:
* Up decreases the length, while Down increases it.
* The previously used chain-length is stored per scene
* Currently, it might be too sensitive. Also, it would help to have some kind of indication of the current chain-length somewhere...
* The chain length specified this way determines the MAXIMUM chain length possible for all chains (if 0, then the default chain-length is used). Chains are clamped to have a chain length which does not exceed the default chain length. This restriction may be removed following further feedback...
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/include/transform.h | 12 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_constraint_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 3 | ||||
-rw-r--r-- | source/blender/src/transform.c | 11 | ||||
-rw-r--r-- | source/blender/src/transform_conversions.c | 132 |
5 files changed, 122 insertions, 39 deletions
diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 52eb3edf19f..b2a3913465f 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -230,7 +230,7 @@ typedef struct TransInfo { // for manipulator exceptions, like scaling using center point, drawing help lines #define T_USES_MANIPULATOR (1 << 7) -/* restrictions flags */ + /* restrictions flags */ #define T_ALL_RESTRICTIONS ((1 << 8)|(1 << 9)|(1 << 10)) #define T_NO_CONSTRAINT (1 << 8) #define T_NULL_ONE (1 << 9) @@ -239,14 +239,17 @@ typedef struct TransInfo { #define T_PROP_EDIT (1 << 11) #define T_PROP_CONNECTED (1 << 12) -/* if MMB is pressed or not */ + /* if MMB is pressed or not */ #define T_MMB_PRESSED (1 << 13) #define T_V3D_ALIGN (1 << 14) -#define T_2D_EDIT (1 << 15) /* for 2d views like uv or ipo */ + /* for 2d views like uv or ipo */ +#define T_2D_EDIT (1 << 15) #define T_CLIP_UV (1 << 16) #define T_FREE_CUSTOMDATA (1 << 17) + /* auto-ik is on */ +#define T_AUTOIK (1 << 18) /* ******************************************************************************** */ @@ -375,6 +378,8 @@ void sort_trans_data_dist(TransInfo *t); void add_tdi_poin(float *poin, float *old, float delta); void special_aftertrans_update(TransInfo *t); +void transform_autoik_update(TransInfo *t, short mode); + /* auto-keying stuff used by special_aftertrans_update */ void autokeyframe_ob_cb_func(struct Object *ob, int tmode); void autokeyframe_pose_cb_func(struct Object *ob, int tmode, short targetless_ik); @@ -458,3 +463,4 @@ char handleNumInput(NumInput *n, unsigned short event); #endif + diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 1b289650e2c..7f9fa49e7a9 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -126,7 +126,8 @@ typedef struct bKinematicConstraint { Object *tar; short iterations; /* Maximum number of iterations to try */ short flag; /* Like CONSTRAINT_IK_TIP */ - int rootbone; /* index to rootbone, if zero go all the way to mother bone */ + short rootbone; /* index to rootbone, if zero go all the way to mother bone */ + short max_rootbone; /* for auto-ik, maximum length of chain */ char subtarget[32]; /* String to specify sub-object target */ Object *poletar; /* Pole vector target */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 2dfe0ac43b6..af64885d9f2 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -363,7 +363,8 @@ typedef struct ToolSettings { short uvcalc_mapalign; short uvcalc_flag; - short pad2; + /* Auto-IK */ + short autoik_chainlen; /* Image Paint (8 byte aligned please!) */ struct ImagePaintSettings imapaint; diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 8a38c66738f..39937c60950 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -815,7 +815,10 @@ static void transformEvent(unsigned short event, short val) { break; case PAGEUPKEY: case WHEELDOWNMOUSE: - if(Trans.flag & T_PROP_EDIT) { + if (Trans.flag & T_AUTOIK) { + transform_autoik_update(&Trans, 1); + } + else if(Trans.flag & T_PROP_EDIT) { Trans.propsize*= 1.1f; calculatePropRatio(&Trans); } @@ -831,7 +834,10 @@ static void transformEvent(unsigned short event, short val) { break; case PAGEDOWNKEY: case WHEELUPMOUSE: - if(Trans.flag & T_PROP_EDIT) { + if (Trans.flag & T_AUTOIK) { + transform_autoik_update(&Trans, -1); + } + else if (Trans.flag & T_PROP_EDIT) { Trans.propsize*= 0.90909090f; calculatePropRatio(&Trans); } @@ -4094,3 +4100,4 @@ void BIF_TransformSetUndo(char *str) } + diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index c84109c54bb..26f1d54569b 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -695,6 +695,62 @@ static void set_pose_transflags(TransInfo *t, Object *ob) t->mode= TFM_ROTATION; } + +/* -------- Auto-IK ---------- */ + +/* adjust pose-channel's auto-ik chainlen */ +static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen) +{ + bConstraint *con; + + /* don't bother to search if no valid constraints */ + if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0) + return; + + /* check if pchan has ik-constraint */ + for (con= pchan->constraints.first; con; con= con->next) { + if (con->type == CONSTRAINT_TYPE_KINEMATIC) { + bKinematicConstraint *data= con->data; + + /* only accept if a temporary one (for auto-ik) */ + if (data->flag & CONSTRAINT_IK_TEMP) { + /* chainlen is new chainlen, but is limited by maximum chainlen */ + if ((chainlen==0) || (chainlen > data->max_rootbone)) + data->rootbone= data->max_rootbone; + else + data->rootbone= chainlen; + printf("chainlen = %d, max = %d, new = %d\n", chainlen, data->max_rootbone, data->rootbone); + } + } + } +} + +/* change the chain-length of auto-ik */ +void transform_autoik_update (TransInfo *t, short mode) +{ + short *chainlen= &G.scene->toolsettings->autoik_chainlen; + bPoseChannel *pchan; + + /* mode determines what change to apply to chainlen */ + if (mode == 1) { + /* mode=1 is from WHEELMOUSEDOWN... increases len */ + (*chainlen)++; + } + else if (mode == -1) { + /* mode==-1 is from WHEELMOUSEUP... decreases len */ + if (*chainlen > 0) (*chainlen)--; + } + + /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */ + if (ELEM(NULL, t->poseobj, t->poseobj->pose)) + return; + + /* apply to all pose-channels */ + for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) { + pchan_autoik_adjust(pchan, *chainlen); + } +} + /* frees temporal IKs */ static void pose_grab_with_ik_clear(Object *ob) { @@ -722,19 +778,19 @@ static void pose_grab_with_ik_clear(Object *ob) } } -/* adds the IK to pchan */ -static void pose_grab_with_ik_add(bPoseChannel *pchan) +/* adds the IK to pchan - returns if added */ +static short pose_grab_with_ik_add(bPoseChannel *pchan) { bKinematicConstraint *data; bConstraint *con; - if (pchan == NULL) { // Sanity check - return; - } + /* Sanity check */ + if (pchan == NULL) + return 0; /* rule: not if there's already an IK on this channel */ for (con= pchan->constraints.first; con; con= con->next) - if(con->type==CONSTRAINT_TYPE_KINEMATIC) + if (con->type==CONSTRAINT_TYPE_KINEMATIC) break; if (con) { @@ -742,7 +798,7 @@ static void pose_grab_with_ik_add(bPoseChannel *pchan) data= has_targetless_ik(pchan); if (data) data->flag |= CONSTRAINT_IK_AUTO; - return; + return 0; } con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC); @@ -764,73 +820,79 @@ static void pose_grab_with_ik_add(bPoseChannel *pchan) data->rootbone++; pchan= pchan->parent; } + + /* make a copy of maximum chain-length */ + data->max_rootbone= data->rootbone; + + return 1; } /* bone is a canditate to get IK, but we don't do it if it has children connected */ -static void pose_grab_with_ik_children(bPose *pose, Bone *bone) +static short pose_grab_with_ik_children(bPose *pose, Bone *bone) { Bone *bonec; - int wentdeeper= 0; + short wentdeeper=0, added=0; /* go deeper if children & children are connected */ - for(bonec= bone->childbase.first; bonec; bonec= bonec->next) { - if(bonec->flag & BONE_CONNECTED) { + for (bonec= bone->childbase.first; bonec; bonec= bonec->next) { + if (bonec->flag & BONE_CONNECTED) { wentdeeper= 1; - pose_grab_with_ik_children(pose, bonec); + added+= pose_grab_with_ik_children(pose, bonec); } } - if(wentdeeper==0) { + if (wentdeeper==0) { bPoseChannel *pchan= get_pose_channel(pose, bone->name); - if(pchan) - pose_grab_with_ik_add(pchan); + if (pchan) + added+= pose_grab_with_ik_add(pchan); } + + return added; } /* main call which adds temporal IK chains */ -static void pose_grab_with_ik(Object *ob) +static short pose_grab_with_ik(Object *ob) { bArmature *arm; bPoseChannel *pchan, *pchansel= NULL; Bone *bonec; - if(ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0) - return; + if (ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0) + return 0; arm = ob->data; /* rule: only one Bone */ - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(pchan->bone->layer & arm->layer) { - if(pchan->bone->flag & BONE_SELECTED) { - if(pchansel) + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if (pchan->bone->layer & arm->layer) { + if (pchan->bone->flag & BONE_SELECTED) { + if (pchansel) break; pchansel= pchan; } } } - if(pchan || pchansel==NULL) return; + if (pchan || pchansel==NULL) return 0; /* rule: no IK for solitary (unconnected) bone */ - for(bonec=pchansel->bone->childbase.first; bonec; bonec=bonec->next) { - if(bonec->flag & BONE_CONNECTED) { + for (bonec=pchansel->bone->childbase.first; bonec; bonec=bonec->next) { + if (bonec->flag & BONE_CONNECTED) { break; } } - if ((pchansel->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL)) return; + if ((pchansel->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL)) return 0; /* rule: if selected Bone is not a root bone, it gets a temporal IK */ - if(pchansel->parent) { + if (pchansel->parent) { /* only adds if there's no IK yet */ - pose_grab_with_ik_add(pchansel); + return pose_grab_with_ik_add(pchansel); } else { /* rule: go over the children and add IK to the tips */ - pose_grab_with_ik_children(ob->pose, pchansel->bone); + return pose_grab_with_ik_children(ob->pose, pchansel->bone); } } - /* only called with pose mode active object now */ static void createTransPose(TransInfo *t, Object *ob) { @@ -838,6 +900,7 @@ static void createTransPose(TransInfo *t, Object *ob) bPoseChannel *pchan; TransData *td; TransDataExtension *tdx; + short ik_on= 0; int i; t->total= 0; @@ -855,8 +918,10 @@ static void createTransPose(TransInfo *t, Object *ob) if (!(ob->lay & G.vd->lay)) return; /* do we need to add temporal IK chains? */ - if((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) - pose_grab_with_ik(ob); + if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) { + ik_on= pose_grab_with_ik(ob); + if (ik_on) t->flag |= T_AUTOIK; + } /* set flags and count total (warning, can change transform to rotate) */ set_pose_transflags(t, ob); @@ -890,6 +955,8 @@ static void createTransPose(TransInfo *t, Object *ob) if(td != (t->data+t->total)) printf("Bone selection count error\n"); + /* initialise initial auto=ik chainlen's? */ + if (ik_on) transform_autoik_update(t, 0); } /* ********************* armature ************** */ @@ -3539,3 +3606,4 @@ void createTransData(TransInfo *t) } + |