- grease pencil option to only use the endpoint depths. this makes drawing shapes...
authorCampbell Barton <ideasman42@gmail.com>
Fri, 1 Jan 2010 17:48:48 +0000 (17:48 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 1 Jan 2010 17:48:48 +0000 (17:48 +0000)
- use a 8x8 area when finding stroke depths since thin lines can get ignored if the point is not close enough to them.

source/blender/editors/gpencil/gpencil_buttons.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/include/ED_view3d.h
source/blender/editors/space_view3d/view3d_edit.c
source/blender/makesdna/DNA_gpencil_types.h
source/blender/makesrna/intern/rna_gpencil.c

index 4f12f072e7258e9bd996e3961b44f80db7b93f0a..e93788bc495c0822aa2d19cdd363ecb92f4cc197 100644 (file)
@@ -266,6 +266,10 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi
                row= uiLayoutRow(col, 1);
                uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "SURFACE");
                uiItemEnumR_string(row, NULL, 0, &gpd_ptr, "draw_mode", "STROKE");
+
+               row= uiLayoutRow(col, 0);
+               uiLayoutSetActive(row, (gpd->flag & GP_DATA_DEPTH_STROKE) ? 1:0);
+               uiItemR(row, NULL, 0, &gpd_ptr, "use_stroke_endpoints", 0);
 }      
 
 
index d48ff411f10a70a1ccb277ad3182bf0c1b7523aa..5efc9d916c1a09bddbf2d9ff65d9dc11159ebc37 100644 (file)
@@ -218,7 +218,7 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[], flo
        
        /* in 3d-space - pt->x/y/z are 3 side-by-side floats */
        if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) {
-               if(gpencil_project_check(p) && (view_autodist_simple(p->ar, mval, out, depth))) {
+               if(gpencil_project_check(p) && (view_autodist_simple(p->ar, mval, out, 0, depth))) {
                        /* projecting onto 3D-Geometry
                         *      - nothing more needs to be done here, since view_autodist_simple() has already done it
                         */
@@ -458,6 +458,8 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
        bGPDspoint *pt;
        tGPspoint *ptc;
        int i, totelem;
+       /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
+       int depth_margin = (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 4 : 0;
        
        /* get total number of points to allocate space for 
         *      - drawing straight-lines only requires the endpoints
@@ -525,7 +527,7 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
 
                        for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size; i++, ptc++, pt++) {
                                mval[0]= ptc->x; mval[1]= ptc->y;
-                               if(view_autodist_depth(p->ar, mval, depth_arr+i) == 0)
+                               if(view_autodist_depth(p->ar, mval, depth_margin, depth_arr+i) == 0)
                                        interp_depth= TRUE;
                                else
                                        found_depth= TRUE;
@@ -537,6 +539,26 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
                                        depth_arr[i] = 0.9999f;
                        }
                        else if(interp_depth) {
+                               if(p->gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) {
+                                       /* remove all info between the valid endpoints */
+                                       int first_valid = 0;
+                                       int last_valid = 0;
+
+                                       for (i=0; i < gpd->sbuffer_size; i++)
+                                               if(depth_arr[i] != FLT_MAX)
+                                                       break;
+                                       first_valid= i;
+
+                                       for (i=gpd->sbuffer_size-1; i >= 0; i--)
+                                               if(depth_arr[i] != FLT_MAX)
+                                                       break;
+                                       last_valid= i;
+
+                                       /* invalidate non-endpoints, so only blend between first and last */
+                                       for (i=first_valid+1; i < last_valid; i++)
+                                               depth_arr[i]= FLT_MAX;
+                               }
+
                                interp_sparse_array(depth_arr, gpd->sbuffer_size, FLT_MAX);
                        }
                }
index b087829d6b0cd4d1e20e12156b4f30e7d272a013..a7879c7b70dcd75fa206e0fc07633731c4803855 100644 (file)
@@ -128,8 +128,8 @@ int view_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, s
 
 /* only draw so view_autodist_simple can be called many times after */
 int view_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode);
-int view_autodist_simple(struct ARegion *ar, short *mval, float mouse_worldloc[3], float *force_depth);
-int view_autodist_depth(struct ARegion *ar, short *mval, float *depth);
+int view_autodist_simple(struct ARegion *ar, short *mval, float mouse_worldloc[3], int margin, float *force_depth);
+int view_autodist_depth(struct ARegion *ar, short *mval, int margin, float *depth);
 
 /* select */
 #define MAXPICKBUF      10000
index 87219b16dd284a543a0d28374ff93c375c4b5b0f..029bb84ca2f2547380222e88920bc2e5a97c57ee 100644 (file)
@@ -1474,7 +1474,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;
@@ -1531,7 +1531,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;
                }
@@ -1559,7 +1559,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];
@@ -2197,22 +2197,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);
@@ -2226,25 +2270,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;
-
-       /* 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_close= view_autodist_depth_margin(ar, mval, 4);
 
-       if (depth_close==MAXFLOAT)
+       if (depth_close==FLT_MAX)
                return 0;
 
        if (had_depth==0) {
@@ -2289,23 +2317,17 @@ int view_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //, flo
 }
 
 // no 4x4 sampling, run view_autodist_init first
-int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3], float *force_depth) //, 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 */
        if(force_depth)
                depth= *force_depth;
        else
-               depth= rv3d->depths->depths[mval[1]*rv3d->depths->w+mval[0]];
+               depth= view_autodist_depth_margin(ar, mval, margin);
 
        if (depth==FLT_MAX)
                return 0;
@@ -2323,24 +2345,9 @@ int view_autodist_simple(ARegion *ar, short *mval, float mouse_worldloc[3], floa
        return 1;
 }
 
-int view_autodist_depth(struct ARegion *ar, short *mval, float *depth)
+int view_autodist_depth(struct ARegion *ar, short *mval, int margin, float *depth)
 {
-       RegionView3D *rv3d= ar->regiondata;
-       *depth= FLT_MAX;
-
-       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]];
-
-       /* float error means we need to shave off some */
-
-       if(*depth >= 1.0) {
-               *depth= FLT_MAX;
-       }
+       *depth= view_autodist_depth_margin(ar, mval, margin);
 
        return (*depth==FLT_MAX) ? 0:1;
                return 0;
index 5755e23675abea8d5b8b104dcdc5041a79d97757..332442b9f42c13f8ba33d1aa9f05d3c6076fe444 100644 (file)
@@ -150,4 +150,6 @@ typedef struct bGPdata {
 #define GP_DATA_DEPTH_VIEW     (1<<5)
 #define GP_DATA_DEPTH_STROKE (1<<6)
 
+#define GP_DATA_DEPTH_STROKE_ENDPOINTS (1<<7)
+
 #endif /*  DNA_GPENCIL_TYPES_H */
index 71c87fe9fa15176c3dc893789ee6b7dc0e4a62cf..87cf9502c6946b59c69d5d8a5c6d2142aad97ac7 100644 (file)
@@ -243,6 +243,12 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
        RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
        RNA_def_property_enum_items(prop, draw_mode_items);
        RNA_def_property_ui_text(prop, "Draw Mode", "");
+
+       prop= RNA_def_property(srna, "use_stroke_endpoints", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_DEPTH_STROKE_ENDPOINTS);
+       RNA_def_property_ui_text(prop, "Only Endpoints", "When snapping the stroke to existing lines, only use the first and last parts of the line.");
+
+
 }
 
 /* --- */