From 7233f22e2171d49060a21a46d5f2d2982dabc789 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 20 Jul 2013 17:12:33 +0000 Subject: add new snap option: 'Selection to Cursor (Offset)', rather then moving everything into the cursor location, the current selection centers around the cursor, maintaining their relative distances. works for mesh, object, pose bones etc. --- source/blender/editors/space_view3d/view3d_snap.c | 130 ++++++++++++++++------ 1 file changed, 97 insertions(+), 33 deletions(-) (limited to 'source/blender/editors/space_view3d/view3d_snap.c') diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 28291971570..fb7bbdaa178 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -64,7 +64,8 @@ #include "WM_api.h" #include "WM_types.h" - +#include "RNA_access.h" +#include "RNA_define.h" #include "ED_armature.h" #include "ED_mesh.h" @@ -79,6 +80,8 @@ /* *********** will get replaced with new transform * */ /* ************************************************** */ +static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]); + typedef struct TransVert { float *loc; float oldloc[3], maploc[3]; @@ -670,7 +673,7 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot) /* *************************************************** */ -static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op)) +static int snap_sel_to_curs(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); @@ -678,10 +681,19 @@ static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op)) TransVert *tv; float imat[3][3], bmat[3][3]; const float *cursor_global; + float center_global[3]; + float offset_global[3]; int a; + const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); + cursor_global = give_cursor(scene, v3d); + if (use_offset) { + snap_curs_to_sel_ex(C, center_global); + sub_v3_v3v3(offset_global, cursor_global, center_global); + } + if (obedit) { float cursor_local[3]; @@ -694,11 +706,25 @@ static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op)) copy_m3_m4(bmat, obedit->obmat); invert_m3_m3(imat, bmat); - tv = transvmain; + /* get the cursor in object space */ sub_v3_v3v3(cursor_local, cursor_global, obedit->obmat[3]); mul_m3_v3(imat, cursor_local); - for (a = 0; a < tottrans; a++, tv++) { - copy_v3_v3(tv->loc, cursor_local); + + if (use_offset) { + float offset_local[3]; + + mul_v3_m3v3(offset_local, imat, offset_global); + + tv = transvmain; + for (a = 0; a < tottrans; a++, tv++) { + add_v3_v3(tv->loc, offset_local); + } + } + else { + tv = transvmain; + for (a = 0; a < tottrans; a++, tv++) { + copy_v3_v3(tv->loc, cursor_local); + } } special_transvert_update(obedit); @@ -717,16 +743,25 @@ static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op)) float cursor_local[3]; invert_m4_m4(ob->imat, ob->obmat); - copy_v3_v3(cursor_local, cursor_global); - mul_m4_v3(ob->imat, cursor_local); - + mul_v3_m4v3(cursor_local, ob->imat, cursor_global); + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone->flag & BONE_SELECTED) { - if (pchan->bone->layer & arm->layer) { + if (PBONE_VISIBLE(arm, pchan->bone)) { if ((pchan->bone->flag & BONE_CONNECTED) == 0) { /* Get position in pchan (pose) space. */ float cursor_pose[3]; - BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose); + + if (use_offset) { + mul_v3_m4v3(cursor_pose, ob->obmat, pchan->pose_mat[3]); + add_v3_v3(cursor_pose, offset_global); + + mul_m4_v3(ob->imat, cursor_pose); + BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose); + } + else { + BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose); + } /* copy new position */ if ((pchan->protectflag & OB_LOCK_LOCX) == 0) @@ -751,9 +786,15 @@ static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op)) } else { float cursor_parent[3]; /* parent-relative */ - cursor_parent[0] = -ob->obmat[3][0] + cursor_global[0]; - cursor_parent[1] = -ob->obmat[3][1] + cursor_global[1]; - cursor_parent[2] = -ob->obmat[3][2] + cursor_global[2]; + + if (use_offset) { + add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); + } + else { + copy_v3_v3(cursor_parent, cursor_global); + } + + sub_v3_v3(cursor_parent, ob->obmat[3]); if (ob->parent) { float originmat[3][3]; @@ -796,6 +837,9 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* rna */ + RNA_def_boolean(ot->srna, "use_offset", 1, "Offset", ""); } /* *************************************************** */ @@ -888,28 +932,29 @@ static void bundle_midpoint(Scene *scene, Object *ob, float vec[3]) } } -static int snap_curs_to_sel(bContext *C, wmOperator *UNUSED(op)) +static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]) { Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); TransVert *tv; - float *curs, bmat[3][3], vec[3], min[3], max[3], centroid[3]; + float bmat[3][3], vec[3], min[3], max[3], centroid[3]; int count, a; - curs = give_cursor(scene, v3d); - count = 0; INIT_MINMAX(min, max); zero_v3(centroid); if (obedit) { tottrans = 0; - + if (ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)) make_trans_verts(obedit, bmat[0], bmat[1], TM_ALL_JOINTS | TM_SKIP_HANDLES); - if (tottrans == 0) return OPERATOR_CANCELLED; - + + if (tottrans == 0) { + return false; + } + copy_m3_m4(bmat, obedit->obmat); tv = transvmain; @@ -923,10 +968,10 @@ static int snap_curs_to_sel(bContext *C, wmOperator *UNUSED(op)) if (v3d->around == V3D_CENTROID) { mul_v3_fl(centroid, 1.0f / (float)tottrans); - copy_v3_v3(curs, centroid); + copy_v3_v3(cursor, centroid); } else { - mid_v3_v3v3(curs, min, max); + mid_v3_v3v3(cursor, min, max); } MEM_freeN(transvmain); transvmain = NULL; @@ -968,19 +1013,38 @@ static int snap_curs_to_sel(bContext *C, wmOperator *UNUSED(op)) } CTX_DATA_END; } - if (count) { - if (v3d->around == V3D_CENTROID) { - mul_v3_fl(centroid, 1.0f / (float)count); - copy_v3_v3(curs, centroid); - } - else { - mid_v3_v3v3(curs, min, max); - } + + if (count == 0) { + return false; + } + + if (v3d->around == V3D_CENTROID) { + mul_v3_fl(centroid, 1.0f / (float)count); + copy_v3_v3(cursor, centroid); + } + else { + mid_v3_v3v3(cursor, min, max); } } - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - - return OPERATOR_FINISHED; + return true; +} + +static int snap_curs_to_sel(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + float *curs; + + curs = give_cursor(scene, v3d); + + if (snap_curs_to_sel_ex(C, curs)) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot) -- cgit v1.2.3