diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-02-05 06:28:07 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-02-05 06:28:07 +0300 |
commit | f89e3d251711f3617c982cae35f33d4c6115e72b (patch) | |
tree | 83b0399aba32a346ae448960f5153e26b2ebdabd | |
parent | 61a6e1957a4a1555564f1eb8dbdb9707fb276826 (diff) |
2.5 - Context API access for Bones (EditMode and PoseMode)
* Added selected, selected+editable, and active to access EditBones for Armature Operators to use. These take into account X-Axis Mirror too, so there is really no need to check that sort of thing anymore in tools.
* Added a quick testing operator for verifying that these loops filter the data correctly. I've dumped this in armature_ops.c for now. It can be activated using the TKEY hotkey in Armature EditMode only. This should be removed once we have a few more functional tools.
* Ported over cleaned up roll-calculation tools from AnimSys2
* Removed a few ugly stubs from posemode code
-rw-r--r-- | source/blender/blenkernel/BKE_context.h | 18 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/context.c | 25 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_ops.c | 54 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature.c | 149 | ||||
-rw-r--r-- | source/blender/editors/armature/poseobject.c | 23 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/space_view3d.c | 86 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 6 |
7 files changed, 276 insertions, 85 deletions
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index c489aba3326..5af97a7d8d5 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -51,6 +51,8 @@ struct StructRNA; struct ToolSettings; struct Image; struct ImBuf; +struct EditBone; +struct bPoseChannel; struct wmWindow; struct wmWindowManager; @@ -81,7 +83,14 @@ enum { CTX_DATA_EDIT_IMAGE, CTX_DATA_EDIT_IMAGE_BUFFER, - CTX_DATA_SELECTED_NODES + CTX_DATA_SELECTED_NODES, + + CTX_DATA_SELECTED_BONES, + CTX_DATA_SELECTED_EDITABLE_BONES, + CTX_DATA_SELECTED_PCHANS, + + CTX_DATA_ACTIVE_BONE, + CTX_DATA_ACTIVE_PCHAN, }; typedef int bContextDataMember; @@ -185,6 +194,13 @@ struct ImBuf *CTX_data_edit_image_buffer(const bContext *C); int CTX_data_selected_nodes(const bContext *C, ListBase *list); +struct EditBone *CTX_data_active_bone(const bContext *C); +int CTX_data_selected_bones(const bContext *C, ListBase *list); +int CTX_data_selected_editable_bones(const bContext *C, ListBase *list); + +struct bPoseChannel *CTX_data_active_pchan(const bContext *C); +int CTX_data_selected_pchans(const bContext *C, ListBase *list); + /* Data Evaluation Context */ float CTX_eval_frame(const bContext *C); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index ccdbea87d87..15e552617a8 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -441,6 +441,31 @@ struct ImBuf *CTX_data_edit_image_buffer(const bContext *C) return ctx_data_pointer_get(C, CTX_DATA_EDIT_IMAGE_BUFFER); } +struct EditBone *CTX_data_active_bone(const bContext *C) +{ + return ctx_data_pointer_get(C, CTX_DATA_ACTIVE_BONE); +} + +int CTX_data_selected_bones(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, CTX_DATA_SELECTED_BONES, list); +} + +int CTX_data_selected_editable_bones(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, CTX_DATA_SELECTED_EDITABLE_BONES, list); +} + +struct bPoseChannel *CTX_data_active_pchan(const bContext *C) +{ + return ctx_data_pointer_get(C, CTX_DATA_ACTIVE_PCHAN); +} + +int CTX_data_selected_pchans(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, CTX_DATA_SELECTED_PCHANS, list); +} + /* data evaluation */ float CTX_eval_frame(const bContext *C) diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index eaa8207bc11..e8f75bd4440 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -58,6 +58,49 @@ #include "armature_intern.h" +/* ************************** quick tests **********************************/ + +/* XXX This is a quick test operator to print names of all EditBones in context + * that should be removed once tool coding starts... + */ + +static int armature_test_exec (bContext *C, wmOperator *op) +{ + printf("EditMode Armature Test: \n"); + + printf("\tSelected Bones \n"); + CTX_DATA_BEGIN(C, EditBone*, ebone, selected_bones) + { + printf("\t\tEditBone '%s' \n", ebone->name); + } + CTX_DATA_END; + + printf("\tEditable Bones \n"); + CTX_DATA_BEGIN(C, EditBone*, ebone, selected_editable_bones) + { + printf("\t\tEditBone '%s' \n", ebone->name); + } + CTX_DATA_END; + + printf("\tActive Bone \n"); + { + EditBone *ebone= CTX_data_active_bone(C); + if (ebone) printf("\t\tEditBone '%s' \n"); + else printf("\t\t<None> \n"); + } + + return OPERATOR_FINISHED; +} + +void ARMATURE_OT_test(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Test Context"; + ot->idname= "ARMATURE_OT_test"; + + /* api callbacks */ + ot->exec= armature_test_exec; +} /* ************************** registration **********************************/ @@ -66,16 +109,23 @@ void ED_operatortypes_armature(void) { WM_operatortype_append(POSE_OT_hide); WM_operatortype_append(POSE_OT_reveil); + + WM_operatortype_append(ARMATURE_OT_test); // XXX temp test for context iterators... to be removed } void ED_keymap_armature(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Armature", 0, 0); + ListBase *keymap; wmKeymapItem *kmi; + /* Armature ------------------------ */ + keymap= WM_keymap_listbase(wm, "Armature", 0, 0); + /* only set in editmode armature, by space_view3d listener */ // WM_keymap_add_item(keymap, "ARMATURE_OT_hide", HKEY, KM_PRESS, 0, 0); - + WM_keymap_add_item(keymap, "ARMATURE_OT_test", TKEY, KM_PRESS, 0, 0); // XXX temp test for context iterators... to be removed + + /* Pose ------------------------ */ /* only set in posemode, by space_view3d listener */ keymap= WM_keymap_listbase(wm, "Pose", 0, 0); diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 631f6ce39df..d083dbec103 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -1844,20 +1844,97 @@ float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3]) return roll; } + +/* Set roll value for given bone -> Z-Axis Point up (original method) */ +void auto_align_ebone_zaxisup(Scene *scene, View3D *v3d, EditBone *ebone) +{ + float delta[3], curmat[3][3]; + float xaxis[3]={1.0f, 0.0f, 0.0f}, yaxis[3], zaxis[3]={0.0f, 0.0f, 1.0f}; + float targetmat[3][3], imat[3][3], diffmat[3][3]; + + /* Find the current bone matrix */ + VecSubf(delta, ebone->tail, ebone->head); + vec_roll_to_mat3(delta, 0.0f, curmat); + + /* Make new matrix based on y axis & z-up */ + VECCOPY(yaxis, curmat[1]); + + Mat3One(targetmat); + VECCOPY(targetmat[0], xaxis); + VECCOPY(targetmat[1], yaxis); + VECCOPY(targetmat[2], zaxis); + Mat3Ortho(targetmat); + + /* Find the difference between the two matrices */ + Mat3Inv(imat, targetmat); + Mat3MulMat3(diffmat, imat, curmat); + + // old-method... let's see if using mat3_to_vec_roll is more accurate + //ebone->roll = atan2(diffmat[2][0], diffmat[2][2]); + mat3_to_vec_roll(diffmat, delta, &ebone->roll); +} + +/* Set roll value for given bone -> Z-Axis point towards cursor */ +void auto_align_ebone_tocursor(Scene *scene, View3D *v3d, EditBone *ebone) +{ + Object *obedit= scene->obedit; // XXX get from context + float *cursor= give_cursor(scene, v3d); + float delta[3], curmat[3][3]; + float mat[4][4], tmat[4][4], imat[4][4]; + float rmat[4][4], rot[3]; + float vec[3]; + + /* find the current bone matrix as a 4x4 matrix (in Armature Space) */ + VecSubf(delta, ebone->tail, ebone->head); + vec_roll_to_mat3(delta, ebone->roll, curmat); + Mat4CpyMat3(mat, curmat); + VECCOPY(mat[3], ebone->head); + + /* multiply bone-matrix by object matrix (so that bone-matrix is in WorldSpace) */ + Mat4MulMat4(tmat, mat, obedit->obmat); + Mat4Invert(imat, tmat); + + /* find position of cursor relative to bone */ + VecMat4MulVecfl(vec, imat, cursor); + + /* check that cursor is in usable position */ + if ((IS_EQ(vec[0], 0)==0) && (IS_EQ(vec[2], 0)==0)) { + /* Compute a rotation matrix around y */ + rot[1] = atan2(vec[0], vec[2]); + rot[0] = rot[2] = 0.0f; + EulToMat4(rot, rmat); + + /* Multiply the bone matrix by rotation matrix. This should be new bone-matrix */ + Mat4MulMat4(tmat, rmat, mat); + Mat3CpyMat4(curmat, tmat); + + /* Now convert from new bone-matrix, back to a roll value (in radians) */ + mat3_to_vec_roll(curmat, delta, &ebone->roll); + } +} + /* Sets the roll value of selected bones, depending on the mode * mode == 0: their z-axes point upwards * mode == 1: their z-axes point towards 3d-cursor */ void auto_align_armature(Scene *scene, View3D *v3d, short mode) { - Object *obedit= scene->obedit; // XXX get from context + Object *obedit= scene->obedit; bArmature *arm= obedit->data; EditBone *ebone; EditBone *flipbone = NULL; - float delta[3]; - float curmat[3][3]; - float *cursor= give_cursor(scene, v3d); - + void (*roll_func)(Scene *, View3D *, EditBone *) = NULL; + + /* specific method used to calculate roll depends on mode */ + switch (mode) { + case 1: /* Z-Axis point towards cursor */ + roll_func= auto_align_ebone_tocursor; + break; + default: /* Z-Axis Point Up */ + roll_func= auto_align_ebone_zaxisup; + break; + } + for (ebone = arm->edbo->first; ebone; ebone=ebone->next) { if (EBONE_VISIBLE(arm, ebone)) { if (arm->flag & ARM_MIRROR_EDIT) @@ -1866,65 +1943,8 @@ void auto_align_armature(Scene *scene, View3D *v3d, short mode) if ((ebone->flag & BONE_SELECTED) || (flipbone && (flipbone->flag & BONE_SELECTED))) { - /* specific method used to calculate roll depends on mode */ - if (mode == 1) { - /* Z-Axis point towards cursor */ - float mat[4][4], tmat[4][4], imat[4][4]; - float rmat[4][4], rot[3]; - float vec[3]; - - /* find the current bone matrix as a 4x4 matrix (in Armature Space) */ - VecSubf(delta, ebone->tail, ebone->head); - vec_roll_to_mat3(delta, ebone->roll, curmat); - Mat4CpyMat3(mat, curmat); - VECCOPY(mat[3], ebone->head); - - /* multiply bone-matrix by object matrix (so that bone-matrix is in WorldSpace) */ - Mat4MulMat4(tmat, mat, obedit->obmat); - Mat4Invert(imat, tmat); - - /* find position of cursor relative to bone */ - VecMat4MulVecfl(vec, imat, cursor); - - /* check that cursor is in usable position */ - if ((IS_EQ(vec[0], 0)==0) && (IS_EQ(vec[2], 0)==0)) { - /* Compute a rotation matrix around y */ - rot[1] = atan2(vec[0], vec[2]); - rot[0] = rot[2] = 0.0f; - EulToMat4(rot, rmat); - - /* Multiply the bone matrix by rotation matrix. This should be new bone-matrix */ - Mat4MulMat4(tmat, rmat, mat); - Mat3CpyMat4(curmat, tmat); - - /* Now convert from new bone-matrix, back to a roll value (in radians) */ - mat3_to_vec_roll(curmat, delta, &ebone->roll); - } - } - else { - /* Z-Axis Point Up */ - float xaxis[3]={1.0, 0.0, 0.0}, yaxis[3], zaxis[3]={0.0, 0.0, 1.0}; - float targetmat[3][3], imat[3][3], diffmat[3][3]; - - /* Find the current bone matrix */ - VecSubf(delta, ebone->tail, ebone->head); - vec_roll_to_mat3(delta, 0.0, curmat); - - /* Make new matrix based on y axis & z-up */ - VECCOPY (yaxis, curmat[1]); - - Mat3One(targetmat); - VECCOPY (targetmat[0], xaxis); - VECCOPY (targetmat[1], yaxis); - VECCOPY (targetmat[2], zaxis); - Mat3Ortho(targetmat); - - /* Find the difference between the two matrices */ - Mat3Inv(imat, targetmat); - Mat3MulMat3(diffmat, imat, curmat); - - ebone->roll = atan2(diffmat[2][0], diffmat[2][2]); - } + /* roll func is a callback which assumes that all is well */ + roll_func(scene, v3d, ebone); } } } @@ -3539,6 +3559,7 @@ static int clear_active_flag(Object *ob, Bone *bone, void *data) } +// XXX bone_looper is only to be used when we want to access settings (i.e. editability/visibility/selected) that context doesn't offer static int bone_looper(Object *ob, Bone *bone, void *data, int (*bone_func)(Object *, Bone *, void *)) { diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index bb883c5a98d..0771806a4a2 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -91,11 +91,10 @@ static void error() {}; static void BIF_undo_push() {} static void countall() {} static void add_constraint() {} -static void select_actionchannel_by_name() {} static void autokeyframe_pose_cb_func() {} /* ************* XXX *************** */ - +/* This function is used to indicate that a bone is selected and needs keyframes inserted */ void set_pose_keys (Object *ob) { bArmature *arm= ob->data; @@ -104,16 +103,15 @@ void set_pose_keys (Object *ob) if (ob->pose){ for (chan=ob->pose->chanbase.first; chan; chan=chan->next){ Bone *bone= chan->bone; - if(bone && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer)) { - chan->flag |= POSE_KEY; - } - else { + if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer)) + chan->flag |= POSE_KEY; + else chan->flag &= ~POSE_KEY; - } } } } +/* This function is used to process the necessary updates for */ void ED_armature_enter_posemode(bContext *C, Base *base) { Object *ob= base->object; @@ -472,9 +470,7 @@ void pose_select_hierarchy(Scene *scene, short direction, short add_to_sel) curbone->flag &= ~BONE_ACTIVE; pabone->flag |= (BONE_ACTIVE|BONE_SELECTED); - // XXX this is evil... this sort of stuff is to be handled in one go as a result of a notifier - select_actionchannel_by_name (ob->action, pchan->name, 0); - select_actionchannel_by_name (ob->action, pchan->parent->name, 1); + // XXX notifiers need to be sent to other editors to update break; } } else { // BONE_SELECT_CHILD @@ -488,9 +484,7 @@ void pose_select_hierarchy(Scene *scene, short direction, short add_to_sel) curbone->flag &= ~BONE_ACTIVE; chbone->flag |= (BONE_ACTIVE|BONE_SELECTED); - // XXX this is evil... this sort of stuff is to be handled in one go as a result of a notifier - select_actionchannel_by_name (ob->action, pchan->name, 0); - select_actionchannel_by_name (ob->action, pchan->child->name, 1); + // XXX notifiers need to be sent to other editors to update break; } } @@ -1339,8 +1333,7 @@ void pose_activate_flipped_bone(Scene *scene) DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA); } - // XXX this is evil... this sort of stuff is to be handled in one go as a result of a notifier - select_actionchannel_by_name(ob->action, name, 1); + // XXX notifiers need to be sent to other editors to update } } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 3f47ec57a50..cdc38879d56 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -29,6 +29,8 @@ #include <string.h> #include <stdio.h> +#include "DNA_action_types.h" +#include "DNA_armature_types.h" #include "DNA_object_types.h" #include "DNA_space_types.h" #include "DNA_scene_types.h" @@ -46,6 +48,7 @@ #include "BKE_screen.h" #include "BKE_utildefines.h" +#include "ED_armature.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -458,6 +461,89 @@ static int view3d_context(const bContext *C, bContextDataMember member, bContext return 1; } + else if(ELEM(member, CTX_DATA_SELECTED_BONES, CTX_DATA_SELECTED_EDITABLE_BONES)) { + Object *obedit= scene->obedit; // XXX get from context? + bArmature *arm= (obedit) ? obedit->data : NULL; + EditBone *ebone, *flipbone=NULL; + + if (arm && arm->edbo) { + /* Attention: X-Axis Mirroring is also handled here... */ + for (ebone= arm->edbo->first; ebone; ebone= ebone->next) { + /* first and foremost, bone must be visible */ + if (EBONE_VISIBLE(arm, ebone)) { + /* get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled + * so that users of this data don't need to check for it themselves + */ + if (arm->flag & ARM_MIRROR_EDIT) + flipbone = armature_bone_get_mirrored(arm->edbo, ebone); + + /* if we're filtering for editable too, use the check for that instead, as it has selection check too */ + if (member == CTX_DATA_SELECTED_EDITABLE_BONES) { + /* only selected + editable */ + if ( EBONE_EDITABLE(ebone) || + ((flipbone) && EBONE_EDITABLE(flipbone)) ) + { + CTX_data_list_add(result, ebone); + } + } + else { + /* only include if bone is selected */ + if ( (ebone->flag & BONE_SELECTED) || + ((flipbone) && (flipbone->flag & BONE_SELECTED)) ) + { + CTX_data_list_add(result, ebone); + } + } + } + } + + return 1; + } + } + else if(member == CTX_DATA_SELECTED_PCHANS) { + Object *obact= OBACT; + bArmature *arm= (obact) ? obact->data : NULL; + bPoseChannel *pchan; + + if (obact && arm) { + for (pchan= obact->pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (arm->layer & pchan->bone->layer)) { + CTX_data_list_add(result, pchan); + } + } + + return 1; + } + } + else if(member == CTX_DATA_ACTIVE_BONE) { + Object *obedit= scene->obedit; // XXX get from context? + bArmature *arm= (obedit) ? obedit->data : NULL; + EditBone *ebone; + + if (arm && arm->edbo) { + for (ebone= arm->edbo->first; ebone; ebone= ebone->next) { + if (EBONE_VISIBLE(arm, ebone)) { + if (ebone->flag & BONE_ACTIVE) { + CTX_data_pointer_set(result, ebone); + + return 1; + } + } + } + } + + } + else if(member == CTX_DATA_ACTIVE_PCHAN) { + Object *obact= OBACT; + bArmature *arm= (obact) ? obact->data : NULL; + bPoseChannel *pchan; + + pchan= get_active_posechannel(obact); + if (pchan) { + CTX_data_pointer_set(result, pchan); + return 1; + } + } return 0; } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index d59961465e7..ebe8341ffc5 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -3440,12 +3440,12 @@ void remake_graph_transdata (TransInfo *t, ListBase *anim_data) sort_time_beztmaps(bezm, fcu->totvert); beztmap_to_data(t, fcu, bezm, fcu->totvert); - /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */ - sort_time_fcurve(fcu); - /* free mapping stuff */ MEM_freeN(bezm); + /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */ + sort_time_fcurve(fcu); + /* make sure handles are all set correctly */ testhandles_fcurve(fcu); } |