diff --git a/source/blender/include/BIF_poseobject.h b/source/blender/include/BIF_poseobject.h index ec7df157b06..7a73384c319 100644 --- a/source/blender/include/BIF_poseobject.h +++ b/source/blender/include/BIF_poseobject.h @@ -35,6 +35,7 @@ struct Object; +struct bPose; struct bPoseChannel; void enter_posemode(void); @@ -60,6 +61,13 @@ void paste_posebuf (int flip); void pose_adds_vgroups(struct Object *meshobj, int heatweights); +void pose_add_posegroup(void); +void pose_remove_posegroup(void); +char *build_posegroups_menustr(struct bPose *pose, short for_pupmenu); +void pose_assign_to_posegroup(void); +void pose_remove_from_posegroup(void); +void pgroup_operation_with_menu(void); + void pose_calculate_path(struct Object *ob); void pose_recalculate_paths(struct Object *ob); void pose_clear_paths(struct Object *ob); diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 6bcb4319d2a..4bd16f16027 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -3854,44 +3854,17 @@ void do_armbuts(unsigned short event) } break; - // TODO: make these pose-group options proper tools in poseobject.c case B_POSEGRP_RECALC: allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); break; case B_POSEGRP_ADD: - if (ob && ob->pose) { - bPose *pose= ob->pose; - bActionGroup *grp; - - grp= MEM_callocN(sizeof(bActionGroup), "PoseGroup"); - strcpy(grp->name, "Group"); - BLI_addtail(&pose->agroups, grp); - BLI_uniquename(&pose->agroups, grp, "Group", offsetof(bActionGroup, name), 32); - - pose->active_group= BLI_countlist(&pose->agroups); - - BIF_undo_push("Add Pose Group"); - allqueue(REDRAWBUTSEDIT, 0); - allqueue(REDRAWVIEW3D, 0); - } + if (ob && ob->pose) + pose_add_posegroup(); break; case B_POSEGRP_REMOVE: - if (ob && ob->pose && ob->pose->active_group) { - bPose *pose= ob->pose; - bActionGroup *grp= NULL; - - // FIXME: make sure all that referenced it get reset - grp= BLI_findlink(&pose->agroups, pose->active_group-1); - if (grp) { - BLI_freelinkN(&pose->agroups, grp); - pose->active_group= 0; - } - - BIF_undo_push("Remove Pose Group"); - allqueue(REDRAWBUTSEDIT, 0); - allqueue(REDRAWVIEW3D, 0); - } + if (ob && ob->pose) + pose_remove_posegroup(); break; } } @@ -4323,37 +4296,6 @@ static int ob_arm_bone_pchan_lock(Object *ob, bArmature *arm, Bone *bone, bPoseC return 0; } -static char *build_posegroups_menustr(bPose *pose) -{ - DynStr *pupds= BLI_dynstr_new(); - bActionGroup *agrp; - char *str; - char buf[16]; - int i; - - /* add title first (and the "none" entry) */ - BLI_dynstr_append(pupds, "Pose Group%t|"); - BLI_dynstr_append(pupds, "BG: [None]%x0|"); - - /* loop through markers, adding them */ - for (agrp= pose->agroups.first, i=1; agrp; agrp=agrp->next, i++) { - BLI_dynstr_append(pupds, "BG: "); - BLI_dynstr_append(pupds, agrp->name); - - sprintf(buf, "%%x%d", i); - BLI_dynstr_append(pupds, buf); - - if (agrp->next) - BLI_dynstr_append(pupds, "|"); - } - - /* convert to normal MEM_malloc'd string */ - str= BLI_dynstr_get_cstring(pupds); - BLI_dynstr_free(pupds); - - return str; -} - static void editing_panel_pose_bones(Object *ob, bArmature *arm) { uiBlock *block; @@ -4388,7 +4330,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm) uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob); /* Bone custom drawing */ - menustr= build_posegroups_menustr(ob->pose); + menustr= build_posegroups_menustr(ob->pose, 0); uiDefButS(block, MENU,REDRAWVIEW3D, menustr, 107,by,105,19, &pchan->agrp_index, 0, 0.0, 0.0, 0.0, "Change the Pose Group this Bone belongs to"); MEM_freeN(menustr); @@ -5211,7 +5153,7 @@ static void editing_panel_links(Object *ob) uiBlockBeginAlign(block); /* currently 'active' group - browse groups */ count= BLI_countlist(&pose->agroups); - menustr= build_posegroups_menustr(pose); + menustr= build_posegroups_menustr(pose, 0); uiDefButI(block, MENU, B_POSEGRP_RECALC, menustr, xco, 85,18,20, &pose->active_group, 1, count, 0, 0, "Browses Pose Groups available for Armature. Click to change."); MEM_freeN(menustr); @@ -5220,7 +5162,7 @@ static void editing_panel_links(Object *ob) bActionGroup *grp= (bActionGroup *)BLI_findlink(&pose->agroups, pose->active_group-1); /* active group */ - but= uiDefBut(block, TEX, REDRAWBUTSEDIT,"", xco+18,85,140-18-20,20, grp->name, 0, 63, 0, 0, "Displays current Pose Group name. Click to change."); + but= uiDefBut(block, TEX, REDRAWBUTSEDIT,"", xco+18,85,140-18-20,20, grp->name, 0, 31, 0, 0, "Displays current Pose Group name. Click to change."); uiButSetFunc(but, verify_posegroup_groupname, pose, grp); uiDefIconBut(block, BUT, B_POSEGRP_REMOVE, VICON_X, xco+140-20, 85, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove this Pose Group"); diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index ab647444a20..95192e42a5d 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -981,12 +981,14 @@ void action_groups_group (short add_group) /* make sure not already in new-group */ if (achan->grp != agrp) { - if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) { - /* unlink from everything else */ - action_groups_removeachan(act, achan); - - /* add to end of group's channels */ - action_groups_addachan(act, agrp, achan); + if ((achan->grp) && (EXPANDED_AGRP(achan->grp))) { + if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) { + /* unlink from everything else */ + action_groups_removeachan(act, achan); + + /* add to end of group's channels */ + action_groups_addachan(act, agrp, achan); + } } } } diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 1a085e19be3..0b55e4c9a68 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -33,6 +33,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" +#include "BLI_dynstr.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" @@ -910,10 +911,213 @@ void pose_adds_vgroups(Object *meshobj, int heatweights) /* ********************************************** */ /* adds a new pose-group */ -// TODO... void pose_add_posegroup () { + Object *ob= OBACT; + bPose *pose= (ob) ? ob->pose : NULL; + bActionGroup *grp; + + if (ELEM(NULL, ob, ob->pose)) + return; + + grp= MEM_callocN(sizeof(bActionGroup), "PoseGroup"); + strcpy(grp->name, "Group"); + BLI_addtail(&pose->agroups, grp); + BLI_uniquename(&pose->agroups, grp, "Group", offsetof(bActionGroup, name), 32); + + pose->active_group= BLI_countlist(&pose->agroups); + + BIF_undo_push("Add Bone Group"); + + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWVIEW3D, 0); +} +/* Remove the active bone-group */ +void pose_remove_posegroup () +{ + Object *ob= OBACT; + bPose *pose= (ob) ? ob->pose : NULL; + bActionGroup *grp = NULL; + bPoseChannel *pchan; + + /* sanity checks */ + if (ELEM(NULL, ob, pose)) + return; + if (pose->active_group <= 0) + return; + + /* get group to remove */ + grp= BLI_findlink(&pose->agroups, pose->active_group-1); + if (grp) { + /* firstly, make sure nothing references it */ + for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { + if (pchan->agrp_index == pose->active_group) + pchan->agrp_index= 0; + } + + /* now, remove it from the pose */ + BLI_freelinkN(&pose->agroups, grp); + pose->active_group= 0; + + BIF_undo_push("Remove Bone Group"); + } + + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWVIEW3D, 0); +} + +char *build_posegroups_menustr (bPose *pose, short for_pupmenu) +{ + DynStr *pupds= BLI_dynstr_new(); + bActionGroup *grp; + char *str; + char buf[16]; + int i; + + /* add title first (and the "none" entry) */ + BLI_dynstr_append(pupds, "Bone Group%t|"); + if (for_pupmenu) + BLI_dynstr_append(pupds, "Add New%x0|"); + else + BLI_dynstr_append(pupds, "BG: [None]%x0|"); + + /* loop through markers, adding them */ + for (grp= pose->agroups.first, i=1; grp; grp=grp->next, i++) { + if (for_pupmenu == 0) + BLI_dynstr_append(pupds, "BG: "); + BLI_dynstr_append(pupds, grp->name); + + sprintf(buf, "%%x%d", i); + BLI_dynstr_append(pupds, buf); + + if (grp->next) + BLI_dynstr_append(pupds, "|"); + } + + /* convert to normal MEM_malloc'd string */ + str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); + + return str; +} + +/* Assign selected pchans to the bone group that the user selects */ +void pose_assign_to_posegroup () +{ + Object *ob= OBACT; + bArmature *arm= (ob) ? ob->data : NULL; + bPose *pose= (ob) ? ob->pose : NULL; + bPoseChannel *pchan; + char *menustr; + int nr; + short done= 0; + + /* sanity checks */ + if (ELEM3(NULL, ob, pose, arm)) + return; + + /* get group to affect */ + menustr= build_posegroups_menustr(pose, 1); + nr= pupmenu(menustr); + MEM_freeN(menustr); + + if (nr < 0) + return; + else if (nr == 0) { + /* add new - note: this does an undo push and sets active group */ + pose_add_posegroup(); + } + else + pose->active_group= nr; + + /* add selected bones to group then */ + for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) { + pchan->agrp_index= pose->active_group; + done= 1; + } + } + + if (done) + BIF_undo_push("Add Bones To Group"); + + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWVIEW3D, 0); +} + +/* Remove selected pchans from their bone groups */ +void pose_remove_from_posegroups () +{ + Object *ob= OBACT; + bArmature *arm= (ob) ? ob->data : NULL; + bPose *pose= (ob) ? ob->pose : NULL; + bPoseChannel *pchan; + short done= 0; + + /* sanity checks */ + if (ELEM3(NULL, ob, pose, arm)) + return; + + /* remove selected bones from their groups */ + for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) { + if (pchan->agrp_index) { + pchan->agrp_index= 0; + done= 1; + } + } + } + + if (done) + BIF_undo_push("Remove Bones From Groups"); + + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWVIEW3D, 0); +} + +/* Ctrl-G in 3D-View while in PoseMode */ +void pgroup_operation_with_menu (void) +{ + Object *ob= OBACT; + bArmature *arm= (ob) ? ob->data : NULL; + bPose *pose= (ob) ? ob->pose : NULL; + bPoseChannel *pchan= NULL; + int mode; + + /* sanity checks */ + if (ELEM3(NULL, ob, pose, arm)) + return; + + /* check that something is selected */ + for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) + break; + } + if (pchan == NULL) + return; + + /* get mode of action */ + if (pchan) + mode= pupmenu("Bone Groups%t|Add Selected to Group%x1|Add New Group%x2|Remove Selected From Groups%x3|Remove Active Group%x4"); + else + mode= pupmenu("Bone Groups%t|Add New Group%x2|Remove Active Group%x4"); + + /* handle mode */ + switch (mode) { + case 1: + pose_assign_to_posegroup(); + break; + case 2: + pose_add_posegroup(); + break; + case 3: + pose_remove_from_posegroups(); + break; + case 4: + pose_remove_posegroup(); + break; + } } /* ********************************************** */ diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 1e764d98e9e..3d4a85bbcd8 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1940,6 +1940,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(ELEM(G.obedit->type, OB_MESH, OB_LATTICE)) vgroup_assign_with_menu(); } + else if(ob && (ob->flag & OB_POSEMODE)) + pgroup_operation_with_menu(); else group_operation_with_menu(); }