Multitouch trackpad 2 fingers gestures implementation
[blender-staging.git] / source / blender / editors / space_view3d / view3d_edit.c
index 30ac41dd15abe3ec7ef145e20fea80d40a0db936..288918c3c1e9f0a39c2c2afe4597a6b5b7b4c8f2 100644 (file)
@@ -234,6 +234,10 @@ typedef struct ViewOpsData {
        ARegion *ar;
        RegionView3D *rv3d;
 
+       /* needed for continuous zoom */
+       wmTimer *timer;
+       double timer_lastdraw;
+
        float oldquat[4];
        float trackvec[3];
        float reverse, dist0;
@@ -300,7 +304,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event)
        if (vod->use_dyn_ofs) {
                VECCOPY(vod->ofs, rv3d->ofs);
                /* If there's no selection, lastofs is unmodified and last value since static */
-               calculateTransformCenter(C, event, V3D_CENTROID, lastofs);
+               calculateTransformCenter(C, V3D_CENTROID, lastofs);
                VECCOPY(vod->dyn_ofs, lastofs);
                mul_v3_fl(vod->dyn_ofs, -1.0f);
        }
@@ -372,6 +376,9 @@ static void viewops_data_free(bContext *C, wmOperator *op)
        if(p && (p->flags & PAINT_FAST_NAVIGATE))
                ED_region_tag_redraw(vod->ar);
 
+       if(vod->timer)
+               WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), vod->timer);
+
        MEM_freeN(vod);
        op->customdata= NULL;
 }
@@ -438,7 +445,9 @@ enum {
 #define VIEW_MODAL_CONFIRM                             1 /* used for all view operations */
 #define VIEWROT_MODAL_AXIS_SNAP_ENABLE 2
 #define VIEWROT_MODAL_AXIS_SNAP_DISABLE        3
-
+#define VIEWROT_MODAL_SWITCH_ZOOM              4
+#define VIEWROT_MODAL_SWITCH_MOVE              5
+#define VIEWROT_MODAL_SWITCH_ROTATE            6
 
 /* called in transform_ops.c, on each regeneration of keymaps  */
 void viewrotate_modal_keymap(wmKeyConfig *keyconf)
@@ -447,7 +456,10 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf)
        {VIEW_MODAL_CONFIRM,    "CONFIRM", 0, "Cancel", ""},
 
        {VIEWROT_MODAL_AXIS_SNAP_ENABLE,        "AXIS_SNAP_ENABLE", 0, "Enable Axis Snap", ""},
-       {VIEWROT_MODAL_AXIS_SNAP_DISABLE,       "AXIS_SNAP_DISABLE", 0, "Enable Axis Snap", ""},
+       {VIEWROT_MODAL_AXIS_SNAP_DISABLE,       "AXIS_SNAP_DISABLE", 0, "Disable Axis Snap", ""},
+               
+       {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
+       {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
 
        {0, NULL, 0, NULL, NULL}};
 
@@ -462,9 +474,13 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf)
        WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
        WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
 
-       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_ENABLE);
-       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_DISABLE);
+       WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_ENABLE);
+       WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_DISABLE);
 
+       WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+       WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+       
        /* assign map to operators */
        WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate");
 
@@ -538,7 +554,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
                invert_m3_m3(m_inv,m);
 
                /* Determine the direction of the x vector (for rotating up and down) */
-               /* This can likely be compuated directly from the quaternion. */
+               /* This can likely be computed directly from the quaternion. */
                mul_m3_v3(m_inv,xvec);
 
                /* Perform the up/down rotation */
@@ -626,6 +642,14 @@ static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event)
                                vod->axis_snap= FALSE;
                                event_code= VIEW_APPLY;
                                break;
+                       case VIEWROT_MODAL_SWITCH_ZOOM:
+                               WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
+                       case VIEWROT_MODAL_SWITCH_MOVE:
+                               WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
                }
        }
        else if(event->type==vod->origkey && event->val==KM_RELEASE) {
@@ -666,13 +690,46 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event)
                        vod->rv3d->persp= RV3D_PERSP;
                ED_region_tag_redraw(vod->ar);
        }
+       
+       if (event->type == MOUSEPAN) {
+               viewrotate_apply(vod, event->prevx, event->prevy);
+               request_depth_update(CTX_wm_region_view3d(C));
+               
+               viewops_data_free(C, op);
+               
+               return OPERATOR_FINISHED;
+       }
+       else if (event->type == MOUSEROTATE) {
+               /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
+               viewrotate_apply(vod, event->prevx, event->y);
+               request_depth_update(CTX_wm_region_view3d(C));
+               
+               viewops_data_free(C, op);
+               
+               return OPERATOR_FINISHED;
+       }
+       else {          
+               /* add temp handler */
+               WM_event_add_modal_handler(C, op);
 
-       /* add temp handler */
-       WM_event_add_modal_handler(C, op);
-
-       return OPERATOR_RUNNING_MODAL;
+               return OPERATOR_RUNNING_MODAL;
+       }
 }
 
+static int ED_operator_view3d_rotate(bContext *C)
+{
+       if (!ED_operator_view3d_active(C)) {
+               return 0;
+       } else {
+               RegionView3D *rv3d= CTX_wm_region_view3d(C);
+               /* rv3d is null in menus, but it's ok when the menu is clicked on */
+               /* XXX of course, this doesn't work with quadview
+                * Maybe having exec return PASSTHROUGH would be better than polling here
+                * Poll functions are full of problems anyway.
+                * */
+               return rv3d == NULL || rv3d->viewlock == 0;
+       }
+}
 
 void VIEW3D_OT_rotate(wmOperatorType *ot)
 {
@@ -685,7 +742,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
        /* api callbacks */
        ot->invoke= viewrotate_invoke;
        ot->modal= viewrotate_modal;
-       ot->poll= ED_operator_view3d_active;
+       ot->poll= ED_operator_view3d_rotate;
 
        /* flags */
        ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
@@ -715,6 +772,10 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
        WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
        WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
 
+       WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
+       WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+       
        /* assign map to operators */
        WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
 }
@@ -763,6 +824,14 @@ static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
                        case VIEW_MODAL_CONFIRM:
                                event_code= VIEW_CONFIRM;
                                break;
+                       case VIEWROT_MODAL_SWITCH_ZOOM:
+                               WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
+                       case VIEWROT_MODAL_SWITCH_ROTATE:
+                               WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
                }
        }
        else if(event->type==vod->origkey && event->val==KM_RELEASE) {
@@ -788,13 +857,23 @@ static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
        /* makes op->customdata */
        viewops_data_create(C, op, event);
 
-       /* add temp handler */
-       WM_event_add_modal_handler(C, op);
+       if (event->type == MOUSEPAN) {
+               ViewOpsData *vod= op->customdata;
+               viewmove_apply(vod, event->prevx, event->prevy);
+               request_depth_update(CTX_wm_region_view3d(C));
+               
+               viewops_data_free(C, op);               
+               
+               return OPERATOR_FINISHED;
+       }
+       else {
+               /* add temp handler */
+               WM_event_add_modal_handler(C, op);
 
-       return OPERATOR_RUNNING_MODAL;
+               return OPERATOR_RUNNING_MODAL;
+       }
 }
 
-
 void VIEW3D_OT_move(wmOperatorType *ot)
 {
 
@@ -833,6 +912,10 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
        WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
        WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
 
+       WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+       WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+       WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+       
        /* assign map to operators */
        WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
 }
@@ -886,15 +969,19 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
 }
 
 
-static void viewzoom_apply(ViewOpsData *vod, int x, int y)
+static void viewzoom_apply(ViewOpsData *vod, int x, int y, short viewzoom)
 {
        float zfac=1.0;
 
-       if(U.viewzoom==USER_ZOOM_CONT) {
+       if(viewzoom==USER_ZOOM_CONT) {
+               double time= PIL_check_seconds_timer();
+               float time_step= (float)(time - vod->timer_lastdraw);
+
                // oldstyle zoom
-               zfac = 1.0+(float)(vod->origx - x + vod->origy - y)/1000.0;
+               zfac = 1.0f + (((float)(vod->origx - x + vod->origy - y)/20.0) * time_step);
+               vod->timer_lastdraw= time;
        }
-       else if(U.viewzoom==USER_ZOOM_SCALE) {
+       else if(viewzoom==USER_ZOOM_SCALE) {
                int ctr[2], len1, len2;
                // method which zooms based on how far you move the mouse
 
@@ -928,7 +1015,7 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y)
                view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy);
 
 
-       if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (vod->rv3d->persp==RV3D_PERSP)) {
+       if ((U.uiflag & USER_ORBIT_ZBUF) && (viewzoom==USER_ZOOM_CONT) && (vod->rv3d->persp==RV3D_PERSP)) {
                float upvec[3], mat[3][3];
 
                /* Secret apricot feature, translate the view when in continues mode */
@@ -959,7 +1046,10 @@ static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event)
        short event_code= VIEW_PASS;
 
        /* execute the events */
-       if(event->type==MOUSEMOVE) {
+       if (event->type == TIMER && event->customdata == vod->timer) {
+               event_code= VIEW_APPLY;
+       }
+       else if(event->type==MOUSEMOVE) {
                event_code= VIEW_APPLY;
        }
        else if(event->type==EVT_MODAL_MAP) {
@@ -967,6 +1057,14 @@ static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event)
                        case VIEW_MODAL_CONFIRM:
                                event_code= VIEW_CONFIRM;
                                break;
+                       case VIEWROT_MODAL_SWITCH_MOVE:
+                               WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
+                       case VIEWROT_MODAL_SWITCH_ROTATE:
+                               WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL);
+                               event_code= VIEW_CONFIRM;
+                               break;
                }
        }
        else if(event->type==vod->origkey && event->val==KM_RELEASE) {
@@ -974,7 +1072,7 @@ static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event)
        }
 
        if(event_code==VIEW_APPLY) {
-               viewzoom_apply(vod, event->x, event->y);
+               viewzoom_apply(vod, event->x, event->y, U.viewzoom);
        }
        else if (event_code==VIEW_CONFIRM) {
                request_depth_update(CTX_wm_region_view3d(C));
@@ -1038,13 +1136,41 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
                viewzoom_exec(C, op);
        }
        else {
+               ViewOpsData *vod;
+
                /* makes op->customdata */
                viewops_data_create(C, op, event);
 
-               /* add temp handler */
-               WM_event_add_modal_handler(C, op);
+               vod= op->customdata;
 
-               return OPERATOR_RUNNING_MODAL;
+               if (event->type == MOUSEZOOM) {
+                       if (U.uiflag & USER_ZOOM_INVERT) /* Bypass Zoom invert flag */
+                               SWAP(int, event->x, event->prevx);
+
+                       if (U.uiflag & USER_ZOOM_DOLLY_HORIZ) {
+                               vod->origx = vod->oldx = event->x;
+                               viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY);
+                       }
+                       else {
+                               
+                               /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
+                               vod->origy = vod->oldy = event->x;
+                               viewzoom_apply(vod, event->x, event->prevx, USER_ZOOM_DOLLY);
+                       }
+                       request_depth_update(CTX_wm_region_view3d(C));
+                       
+                       viewops_data_free(C, op);
+                       return OPERATOR_FINISHED;
+               }
+               else {
+                       vod->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+                       vod->timer_lastdraw= PIL_check_seconds_timer();
+
+                       /* add temp handler */
+                       WM_event_add_modal_handler(C, op);
+
+                       return OPERATOR_RUNNING_MODAL;
+               }
        }
        return OPERATOR_FINISHED;
 }
@@ -1380,6 +1506,8 @@ static int render_border_exec(bContext *C, wmOperator *op)
        } else {
                scene->r.mode |= R_BORDER;
        }
+       
+       WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, NULL);
 
        return OPERATOR_FINISHED;
 
@@ -1437,7 +1565,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
 
        /* ZBuffer depth vars */
        bglMats mats;
-       float depth, depth_close= MAXFLOAT;
+       float depth, depth_close= FLT_MAX;
        int had_depth = 0;
        double cent[2],  p[3];
        int xs, ys;
@@ -1494,7 +1622,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
                double p_corner[3];
 
                /* no depths to use, we cant do anything! */
-               if (depth_close==MAXFLOAT){
+               if (depth_close==FLT_MAX){
                        BKE_report(op->reports, RPT_ERROR, "Depth Too Large");
                        return OPERATOR_CANCELLED;
                }
@@ -1522,7 +1650,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
                new_dist = rv3d->dist;
 
                /* convert the drawn rectangle into 3d space */
-               if (depth_close!=MAXFLOAT && gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) {
+               if (depth_close!=FLT_MAX && gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) {
                        new_ofs[0] = -p[0];
                        new_ofs[1] = -p[1];
                        new_ofs[2] = -p[2];
@@ -1799,9 +1927,8 @@ static EnumPropertyItem prop_view_orbit_items[] = {
 
 static int vieworbit_exec(bContext *C, wmOperator *op)
 {
-       ARegion *ar= CTX_wm_region(C);
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
-       float phi, si, q1[4];
+       float phi, si, q1[4], new_quat[4];
        int orbitdir;
 
        orbitdir = RNA_enum_get(op->ptr, "type");
@@ -1817,10 +1944,10 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
                                q1[0]= (float)cos(phi);
                                q1[1]= q1[2]= 0.0;
                                q1[3]= si;
-                               mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
+                               mul_qt_qtqt(new_quat, rv3d->viewquat, q1);
                                rv3d->view= 0;
                        }
-                       if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) {
+                       else if(orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3D_VIEW_STEPUP) {
                                /* horizontal axis */
                                VECCOPY(q1+1, rv3d->viewinv[0]);
 
@@ -1832,10 +1959,11 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
                                q1[1]*= si;
                                q1[2]*= si;
                                q1[3]*= si;
-                               mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1);
+                               mul_qt_qtqt(new_quat, rv3d->viewquat, q1);
                                rv3d->view= 0;
                        }
-                       ED_region_tag_redraw(ar);
+
+                       smooth_view(C, NULL, NULL, NULL, new_quat, NULL, NULL);
                }
        }
 
@@ -1851,7 +1979,7 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
 
        /* api callbacks */
        ot->exec= vieworbit_exec;
-       ot->poll= ED_operator_view3d_active;
+       ot->poll= ED_operator_view3d_rotate;
 
        /* flags */
        ot->flag= 0;
@@ -1997,7 +2125,7 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
        view3d_operator_needs_opengl(C);
 
        view3d_set_viewcontext(C, &vc);
-       view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats);
+       view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */
        view3d_calculate_clipping(rv3d->clipbb, rv3d->clip, &mats, &rect);
 
        return OPERATOR_FINISHED;
@@ -2088,14 +2216,10 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
                fp[2]= (rv3d->persinv[0][2]*dx + rv3d->persinv[1][2]*dy+ rv3d->persinv[2][2]*fz)-rv3d->ofs[2];
        }
 
-//     if(lr_click) {
-               // XXX          if(obedit->type==OB_MESH) add_click_mesh();
-               //              else if ELEM(obedit->type, OB_CURVE, OB_SURF) addvert_Nurb(0);
-               //              else if (obedit->type==OB_ARMATURE) addvert_armature();
-//             VECCOPY(fp, oldcurs);
-//     }
-       // XXX notifier for scene */
-       ED_area_tag_redraw(CTX_wm_area(C));
+       if(v3d && v3d->localvd)
+               WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
+       else
+               WM_event_add_notifier(C, NC_SCENE|NA_EDITED, scene);
 
        return OPERATOR_FINISHED;
 }
@@ -2114,7 +2238,7 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
        ot->poll= ED_operator_view3d_active;
     
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+//     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
     
        /* rna later */
 
@@ -2164,22 +2288,66 @@ void VIEW3D_OT_manipulator(wmOperatorType *ot)
 /* ************************* below the line! *********************** */
 
 
+static float view_autodist_depth_margin(ARegion *ar, short *mval, int margin)
+{
+       RegionView3D *rv3d= ar->regiondata;
+       float depth= FLT_MAX;
+
+       if(margin==0) {
+               if (mval[0] < 0) return 0;
+               if (mval[1] < 0) return 0;
+               if (mval[0] >= rv3d->depths->w) return 0;
+               if (mval[1] >= rv3d->depths->h) return 0;
+
+               /* Get Z Depths, needed for perspective, nice for ortho */
+               depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]];
+               if(depth >= rv3d->depths->depth_range[1] || depth <= rv3d->depths->depth_range[0]) {
+                       depth= FLT_MAX;
+               }
+       }
+       else {
+               rcti rect;
+               float depth_close= FLT_MAX;
+               int xs, ys;
+
+               rect.xmax = mval[0] + margin;
+               rect.ymax = mval[1] + margin;
+
+               rect.xmin = mval[0] - margin;
+               rect.ymin = mval[1] - margin;
+
+               /* Constrain rect to depth bounds */
+               if (rect.xmin < 0) rect.xmin = 0;
+               if (rect.ymin < 0) rect.ymin = 0;
+               if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1;
+               if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1;
+
+               /* Find the closest Z pixel */
+               for (xs=rect.xmin; xs < rect.xmax; xs++) {
+                       for (ys=rect.ymin; ys < rect.ymax; ys++) {
+                               depth= rv3d->depths->depths[ys*rv3d->depths->w+xs];
+                               if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) {
+                                       if (depth_close > depth) {
+                                               depth_close = depth;
+                                       }
+                               }
+                       }
+               }
+
+               depth= depth_close;
+       }
+
+       return depth;
+}
+
 /* XXX todo Zooms in on a border drawn by the user */
 int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist )
 {
        RegionView3D *rv3d= ar->regiondata;
        bglMats mats; /* ZBuffer depth vars */
-       rcti rect;
-       float depth, depth_close= MAXFLOAT;
+       float depth_close= FLT_MAX;
        int had_depth = 0;
        double cent[2],  p[3];
-       int xs, ys;
-
-       rect.xmax = mval[0] + 4;
-       rect.ymax = mval[1] + 4;
-
-       rect.xmin = mval[0] - 4;
-       rect.ymin = mval[1] - 4;
 
        /* Get Z Depths, needed for perspective, nice for ortho */
        bgl_get_mats(&mats);
@@ -2193,25 +2361,9 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mou
 
        view3d_update_depths(ar, v3d);
 
-       /* Constrain rect to depth bounds */
-       if (rect.xmin < 0) rect.xmin = 0;
-       if (rect.ymin < 0) rect.ymin = 0;
-       if (rect.xmax >= rv3d->depths->w) rect.xmax = rv3d->depths->w-1;
-       if (rect.ymax >= rv3d->depths->h) rect.ymax = rv3d->depths->h-1;
+       depth_close= view_autodist_depth_margin(ar, mval, 4);
 
-       /* Find the closest Z pixel */
-       for (xs=rect.xmin; xs < rect.xmax; xs++) {
-               for (ys=rect.ymin; ys < rect.ymax; ys++) {
-                       depth= rv3d->depths->depths[ys*rv3d->depths->w+xs];
-                       if(depth < rv3d->depths->depth_range[1] && depth > rv3d->depths->depth_range[0]) {
-                               if (depth_close > depth) {
-                                       depth_close = depth;
-                               }
-                       }
-               }
-       }
-
-       if (depth_close==MAXFLOAT)
+       if (depth_close==FLT_MAX)
                return 0;
 
        if (had_depth==0) {
@@ -2232,12 +2384,19 @@ int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mou
        return 1;
 }
 
-int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d) //, float *autodist )
+int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, float *autodist )
 {
        RegionView3D *rv3d= ar->regiondata;
 
        /* Get Z Depths, needed for perspective, nice for ortho */
-       draw_depth(scene, ar, v3d, NULL);
+       switch(mode) {
+       case 0:
+               draw_depth(scene, ar, v3d, NULL);
+               break;
+       case 1:
+               draw_depth_gpencil(scene, ar, v3d);
+               break;
+       }
 
        /* force updating */
        if (rv3d->depths) {
@@ -2249,28 +2408,25 @@ int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d) //, float *autodi
 }
 
 // no 4x4 sampling, run view_autodist_init first
-int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3] ) //, float *autodist )
+int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3], int margin, float *force_depth) //, float *autodist )
 {
-       RegionView3D *rv3d= ar->regiondata;
        bglMats mats; /* ZBuffer depth vars, could cache? */
        float depth;
        double cent[2],  p[3];
 
-       if (mval[0] < 0) return 0;
-       if (mval[1] < 0) return 0;
-       if (mval[0] >= rv3d->depths->w) return 0;
-       if (mval[1] >= rv3d->depths->h) return 0;
-
        /* Get Z Depths, needed for perspective, nice for ortho */
-       bgl_get_mats(&mats);
-       depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]];
+       if(force_depth)
+               depth= *force_depth;
+       else
+               depth= view_autodist_depth_margin(ar, mval, margin);
 
-       if (depth==MAXFLOAT)
+       if (depth==FLT_MAX)
                return 0;
 
        cent[0] = (double)mval[0];
        cent[1] = (double)mval[1];
 
+       bgl_get_mats(&mats);
        if (!gluUnProject(cent[0], cent[1], depth, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
                return 0;
 
@@ -2280,6 +2436,14 @@ int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3] ) //,
        return 1;
 }
 
+int view_autodist_depth(struct ARegion *ar, short *mval, int margin, float *depth)
+{
+       *depth= view_autodist_depth_margin(ar, mval, margin);
+
+       return (*depth==FLT_MAX) ? 0:1;
+               return 0;
+}
+
 /* ********************* NDOF ************************ */
 /* note: this code is confusing and unclear... (ton) */
 /* **************************************************** */