add new snap option: 'Selection to Cursor (Offset)',
authorCampbell Barton <ideasman42@gmail.com>
Sat, 20 Jul 2013 17:12:33 +0000 (17:12 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sat, 20 Jul 2013 17:12:33 +0000 (17:12 +0000)
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.

release/scripts/startup/bl_ui/space_view3d.py
source/blender/editors/space_view3d/view3d_snap.c

index a5c8e7727b278782036748adc3e638442623182c..19095df6a14147e4e1e416d338c7ff50adbd4d43 100644 (file)
@@ -293,7 +293,10 @@ class VIEW3D_MT_snap(Menu):
         layout = self.layout
 
         layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid")
-        layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor")
+        props = layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor")
+        props.use_offset = False
+        props = layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Offset)")
+        props.use_offset = True
 
         layout.separator()
 
index 28291971570c5070e199fadbf22f4d27928463bc..fb7bbdaa178f9762f8140d0ebd2dab5a7704acb3 100644 (file)
@@ -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)