GPencil: Changes in Fill and new 3D Cursor View Plane
authorAntonioya <blendergit@gmail.com>
Sun, 17 Mar 2019 18:47:31 +0000 (19:47 +0100)
committerAntonioya <blendergit@gmail.com>
Sun, 17 Mar 2019 18:47:56 +0000 (19:47 +0100)
This commit groups several options that were tested in grease pencil branch:

- Changes to fill algorithms and improves, specially in small areas and stroke corners.
  New options has been added in order to define how the fill is working and internally there are optimizations in detect the small areas in the extremes.

  Kudos to @charlie for coding this fill improvements.

- New 3D cursor view plane option.

  Now it's possible to lock the drawing plane to the 3D cursor and use the 3D cursor orientation. This allows more flexibility when you are drawing and reduce the need to create geometry to draw over surfaces.

- Canvas Grid now can be locked to 3D cursor.
- New option to reproject stroke using 3D cursor.
- Small tweaks and fixes.

Changes reviewed by @pepeland and @mendio

21 files changed:
release/scripts/startup/bl_ui/properties_paint_common.py
release/scripts/startup/bl_ui/space_topbar.py
source/blender/blenkernel/intern/brush.c
source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
source/blender/draw/engines/gpencil/gpencil_draw_utils.c
source/blender/draw/engines/gpencil/gpencil_engine.c
source/blender/editors/gpencil/drawgpencil.c
source/blender/editors/gpencil/gpencil_brush.c
source/blender/editors/gpencil/gpencil_edit.c
source/blender/editors/gpencil/gpencil_fill.c
source/blender/editors/gpencil/gpencil_intern.h
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/gpencil/gpencil_primitive.c
source/blender/editors/gpencil/gpencil_utils.c
source/blender/editors/include/ED_gpencil.h
source/blender/gpu/shaders/gpu_shader_gpencil_stroke_geom.glsl
source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert.glsl
source/blender/makesdna/DNA_brush_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_brush.c
source/blender/makesrna/intern/rna_sculpt_paint.c

index 1a1f0fa3fb7eb45b393ed1ee1a4b42403f3de6f0..ac63948d18aa8be2e52cf6d470ba43b13f05ec8b 100644 (file)
@@ -393,7 +393,7 @@ def brush_basic_sculpt_settings(layout, context, brush, *, compact=False):
     layout.row().prop(brush, "direction", expand=True, **({"text": ""} if compact else {}))
 
 
-def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False):
+def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=True):
     gp_settings = brush.gpencil_settings
 
     # Brush details
@@ -412,24 +412,15 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False)
             row = layout.row(align=True)
             row.prop(gp_settings, "eraser_thickness_factor")
     elif brush.gpencil_tool == 'FILL':
-        row = layout.column(align=True)
+        row = layout.row(align=True)
         row.prop(gp_settings, "fill_leak", text="Leak Size")
-        row.separator()
-        row = layout.column(align=True)
+        row = layout.row(align=True)
         row.prop(brush, "size", text="Thickness")
-        row = layout.column(align=True)
+        row = layout.row(align=True)
         row.prop(gp_settings, "fill_simplify_level", text="Simplify")
-
         row = layout.row(align=True)
-        row.prop(gp_settings, "fill_draw_mode", text="Boundary Draw Mode")
+        row.prop(gp_settings, "fill_draw_mode", text="Boundary")
         row.prop(gp_settings, "show_fill_boundary", text="", icon='GRID')
-
-        row = layout.column(align=True)
-        row.enabled = gp_settings.fill_draw_mode != 'STROKE'
-        row.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes")
-        sub = layout.row(align=True)
-        sub.enabled = not gp_settings.show_fill
-        sub.prop(gp_settings, "fill_threshold", text="Threshold")
     else:  # brush.gpencil_tool == 'DRAW':
         row = layout.row(align=True)
         row.prop(brush, "size", text="Radius")
index 4cda2678e3306368da433d67fcd08aba5a88fa0f..73aa59a2693cfde7ae4ccb324317ee032b482e0a 100644 (file)
@@ -362,6 +362,15 @@ class _draw_left_context_mode:
                     panel="TOPBAR_PT_gpencil_primitive",
                     text="Thickness Profile"
                 )
+                
+            if brush.gpencil_tool == 'FILL':
+                settings = context.tool_settings.gpencil_sculpt
+                row = layout.row(align=True)
+                sub = row.row(align=True)
+                sub.popover(
+                    panel="TOPBAR_PT_gpencil_fill",
+                    text="Fill Options"
+                )
 
         @staticmethod
         def SCULPT_GPENCIL(context, layout, tool):
@@ -1036,6 +1045,28 @@ class TOPBAR_PT_gpencil_primitive(Panel):
         # Curve
         layout.template_curve_mapping(settings, "thickness_primitive_curve", brush=True)
 
+# Grease Pencil Fill
+class TOPBAR_PT_gpencil_fill(Panel):
+    bl_space_type = 'VIEW_3D'
+    bl_region_type = 'HEADER'
+    bl_label = "Advanced"
+
+    @staticmethod
+    def draw(self, context):
+        paint = context.tool_settings.gpencil_paint
+        brush = paint.brush
+        gp_settings = brush.gpencil_settings
+
+        layout = self.layout
+        # Fill
+        row = layout.row(align=True)
+        row.prop(gp_settings, "fill_factor", text="Resolution")
+        if gp_settings.fill_draw_mode != 'STROKE':
+            row = layout.row(align=True)
+            row.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes")
+            row = layout.row(align=True)
+            row.prop(gp_settings, "fill_threshold", text="Threshold")
+
 
 classes = (
     TOPBAR_HT_upper_bar,
@@ -1058,6 +1089,7 @@ classes = (
     TOPBAR_PT_active_tool,
     TOPBAR_PT_gpencil_layers,
     TOPBAR_PT_gpencil_primitive,
+    TOPBAR_PT_gpencil_fill,
 )
 
 if __name__ == "__main__":  # only for live edit.
index 2e68c88c5f7990bd79eb00297c30533fe7f2b750..c959504f84fcc688cdc98a6c2b1530fc56c1a89b 100644 (file)
@@ -480,6 +480,7 @@ void BKE_brush_gpencil_presets(bContext *C)
        brush->gpencil_settings->fill_leak = 3;
        brush->gpencil_settings->fill_threshold = 0.1f;
        brush->gpencil_settings->fill_simplylvl = 1;
+       brush->gpencil_settings->fill_factor = 1;
        brush->gpencil_settings->icon_id = GP_BRUSH_ICON_FILL;
        brush->gpencil_tool = GPAINT_TOOL_FILL;
 
index 1f3874e70ba3604bbdc123729a5b88b2f6dcbc6f..b72a6ebebbde95bb16a3149decdc5876de2d7a56 100644 (file)
@@ -270,7 +270,7 @@ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness)
 
        for (int i = 0; i < totpoints; i++, tpt++) {
                ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
-               ED_gp_project_point_to_plane(ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
+               ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
 
                /* first point for adjacency (not drawn) */
                if (i == 0) {
@@ -361,7 +361,7 @@ GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness)
 
        for (int i = 0; i < totpoints; i++, tpt++) {
                ED_gpencil_tpoint_to_point(ar, origin, tpt, &pt);
-               ED_gp_project_point_to_plane(ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
+               ED_gp_project_point_to_plane(scene, ob, rv3d, origin, ts->gp_sculpt.lock_axis - 1, &pt);
 
                /* set point */
                gpencil_set_stroke_point(
index a50b4fac15cc5f86a14523cad1f0339bef4d19e6..2710ecc5e5be630a01b559013fdd160a0d865f7a 100644 (file)
@@ -506,7 +506,7 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(
        DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
 
        /* avoid wrong values */
-       if ((gpd) && (gpd->pixfactor == 0)) {
+       if ((gpd) && (gpd->pixfactor == 0.0f)) {
                gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
        }
 
@@ -627,7 +627,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(
        DRW_shgroup_uniform_float(grp, "pixsize", stl->storage->pixsize, 1);
 
        /* avoid wrong values */
-       if ((gpd) && (gpd->pixfactor == 0)) {
+       if ((gpd) && (gpd->pixfactor == 0.0f)) {
                gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
        }
 
index 5f2652b0bfb55f16a82b509bd333206cc5a4c8bb..7fbae5e98eaa40245f30e44a56afa45c384e08f2 100644 (file)
@@ -582,6 +582,7 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
        Scene *scene = draw_ctx->scene;
        ToolSettings *ts = scene->toolsettings;
        View3D *v3d = draw_ctx->v3d;
+       const View3DCursor *cursor = &scene->cursor;
 
        if (ob->type == OB_GPENCIL && ob->data) {
                bGPdata *gpd = (bGPdata *)ob->data;
@@ -626,7 +627,9 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
                if ((v3d) &&
                    ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) &&
                    (v3d->gp_flag & V3D_GP_SHOW_GRID) &&
-                   (ob->type == OB_GPENCIL) && (ob == draw_ctx->obact))
+                   (ob->type == OB_GPENCIL) && (ob == draw_ctx->obact) &&
+                       ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0) &&
+                       ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) == 0))
                {
                        GPU_BATCH_DISCARD_SAFE(e_data.batch_grid);
                        MEM_SAFE_FREE(e_data.batch_grid);
@@ -634,13 +637,36 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
                        e_data.batch_grid = DRW_gpencil_get_grid(ob);
 
                        /* define grid orientation */
-                       if (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_VIEW) {
-                               copy_m4_m4(stl->storage->grid_matrix, ob->obmat);
+                       switch (ts->gp_sculpt.lock_axis) {
+                               case GP_LOCKAXIS_VIEW:
+                               {
+                                       /* align always to view */
+                                       invert_m4_m4(stl->storage->grid_matrix, draw_ctx->rv3d->viewmat);
+                                       /* copy ob location */
+                                       copy_v3_v3(stl->storage->grid_matrix[3], ob->obmat[3]);
+                                       break;
+                               }
+                               case GP_LOCKAXIS_CURSOR:
+                               {
+                                       float scale[3] = { 1.0f, 1.0f, 1.0f };
+                                       loc_eul_size_to_mat4(stl->storage->grid_matrix,
+                                                                               cursor->location,
+                                                                               cursor->rotation_euler,
+                                                                               scale);
+                                       break;
+                               }
+                               default:
+                               {
+                                       copy_m4_m4(stl->storage->grid_matrix, ob->obmat);
+                                       break;
+                               }
+                       }
+
+                       /* Move the origin to Object or Cursor */
+                       if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
+                               copy_v3_v3(stl->storage->grid_matrix[3], cursor->location);
                        }
                        else {
-                               /* align always to view */
-                               invert_m4_m4(stl->storage->grid_matrix, draw_ctx->rv3d->viewmat);
-                               /* copy ob location */
                                copy_v3_v3(stl->storage->grid_matrix[3], ob->obmat[3]);
                        }
 
index 1ae3176d393cd169fec4b00e23d5172d753e9250..ebe0fa61b218ed49576ddedef6cd3903eae6d681 100644 (file)
@@ -720,9 +720,12 @@ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4
        immUniform1f("objscale", obj_scale);
        int keep_size = (int)((tgpw->gpd) && (tgpw->gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS));
        immUniform1i("keep_size", keep_size);
-       immUniform1i("pixfactor", tgpw->gpd->pixfactor);
+       immUniform1f("pixfactor", tgpw->gpd->pixfactor);
        /* xray mode always to 3D space to avoid wrong zdepth calculation (T60051) */
        immUniform1i("xraymode", GP_XRAY_3DSPACE);
+       immUniform1i("caps_start", (int)tgpw->gps->caps[0]);
+       immUniform1i("caps_end", (int)tgpw->gps->caps[1]);
+       immUniform1i("fill_stroke", (int)tgpw->is_fill_stroke);
 
        /* draw stroke curve */
        GPU_line_width(max_ff(curpressure * thickness, 1.0f));
@@ -733,23 +736,22 @@ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4
                /* first point for adjacency (not drawn) */
                if (i == 0) {
                        gp_set_point_varying_color(points, ink, attr_id.color);
-                       immAttr1f(attr_id.thickness, max_ff(curpressure * thickness, 1.0f));
+                       
                        if ((cyclic) && (totpoints > 2)) {
+                               immAttr1f(attr_id.thickness, max_ff((points + totpoints - 1)->pressure * thickness, 1.0f));
                                mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 1)->x);
                        }
                        else {
+                               immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, 1.0f));
                                mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x);
                        }
-                       mul_v3_fl(fpt, -1.0f);
                        immVertex3fv(attr_id.pos, fpt);
                }
                /* set point */
                gp_set_point_varying_color(pt, ink, attr_id.color);
-               immAttr1f(attr_id.thickness, max_ff(curpressure * thickness, 1.0f));
+               immAttr1f(attr_id.thickness, max_ff(pt->pressure * thickness, 1.0f));
                mul_v3_m4v3(fpt, tgpw->diff_mat, &pt->x);
                immVertex3fv(attr_id.pos, fpt);
-
-               curpressure = pt->pressure;
        }
 
        if (cyclic && totpoints > 2) {
@@ -765,10 +767,9 @@ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4
        }
        /* last adjacency point (not drawn) */
        else {
-               gp_set_point_varying_color(points + totpoints - 1, ink, attr_id.color);
-               immAttr1f(attr_id.thickness, max_ff(curpressure * thickness, 1.0f));
+               gp_set_point_varying_color(points + totpoints - 2, ink, attr_id.color);
+               immAttr1f(attr_id.thickness, max_ff((points + totpoints - 2)->pressure * thickness, 1.0f));
                mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 2)->x);
-               mul_v3_fl(fpt, -1.0f);
                immVertex3fv(attr_id.pos, fpt);
        }
 
@@ -1029,6 +1030,10 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
                /* calculate thickness */
                sthickness = gps->thickness + tgpw->lthick;
 
+               if (tgpw->is_fill_stroke) {
+                       sthickness = (short)max_ii(1, sthickness / 2);
+               }
+
                if (sthickness <= 0) {
                        continue;
                }
@@ -1427,6 +1432,7 @@ static void gp_draw_data_layers(RegionView3D *rv3d,
        tgpw.winx = winx;
        tgpw.winy = winy;
        tgpw.dflag = dflag;
+       tgpw.is_fill_stroke = false;
 
        for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
                /* calculate parent position */
index 0403a42a2c965dfb3a16a1a8d19a08efacf381e2..2df0edd3bf7cc013c221e3172675b7d388f4668e 100644 (file)
@@ -176,18 +176,54 @@ static void gpsculpt_compute_lock_axis(tGP_BrushEditData *gso, bGPDspoint *pt, c
                return;
        }
 
-       ToolSettings *ts = gso->scene->toolsettings;
-       int axis = ts->gp_sculpt.lock_axis;
+       const ToolSettings *ts = gso->scene->toolsettings;
+       const View3DCursor *cursor = &gso->scene->cursor;
+       const int axis = ts->gp_sculpt.lock_axis;
 
        /* lock axis control */
-       if (axis == 1) {
-               pt->x = save_pt[0];
-       }
-       if (axis == 2) {
-               pt->y = save_pt[1];
-       }
-       if (axis == 3) {
-               pt->z = save_pt[2];
+       switch (axis) {
+               case GP_LOCKAXIS_X:
+               {
+                       pt->x = save_pt[0];
+                       break;
+               }
+               case GP_LOCKAXIS_Y:
+               {
+                       pt->y = save_pt[1];
+                       break;
+               }
+               case GP_LOCKAXIS_Z:
+               {
+                       pt->z = save_pt[2];
+                       break;
+               }
+               case GP_LOCKAXIS_CURSOR:
+               {
+                       /* compute a plane with cursor normal and position of the point
+                          before do the sculpt */
+                       const float scale[3] = { 1.0f, 1.0f, 1.0f };
+                       float plane_normal[3] = { 0.0f, 0.0f, 1.0f };
+                       float plane[4];
+                       float mat[4][4];
+                       float r_close[3];
+                       
+                       loc_eul_size_to_mat4(mat,
+                               cursor->location,
+                               cursor->rotation_euler,
+                               scale);
+
+                       mul_mat3_m4_v3(mat, plane_normal);
+                       plane_from_point_normal_v3(plane, save_pt, plane_normal);
+
+                       /* find closest point to the plane with the new position */
+                       closest_to_plane_v3(r_close, plane, &pt->x);
+                       copy_v3_v3(&pt->x, r_close);
+                       break;
+               }
+               default:
+               {
+                       break;
+               }
        }
 }
 
index 1388beb0b207437c71f21800fd48fcf316c2f101..f14ba3b4f27c14494c80c4facd04ec9e2b1e478b 100644 (file)
@@ -3280,6 +3280,8 @@ typedef enum eGP_ReprojectModes {
        GP_REPROJECT_VIEW,
        /* Reprojected on to the scene geometry */
        GP_REPROJECT_SURFACE,
+       /* Reprojected on 3D cursor orientation */
+       GP_REPROJECT_CURSOR,
 } eGP_ReprojectModes;
 
 static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
@@ -3334,10 +3336,17 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
                                gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
 
                                /* Project stroke in one axis */
-                               if (ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP)) {
-                                       ED_gp_get_drawing_reference(
-                                               scene, ob, gpl,
-                                               ts->gpencil_v3d_align, origin);
+                               if (ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE,
+                                                          GP_REPROJECT_TOP, GP_REPROJECT_CURSOR))
+                               {
+                                       if (mode != GP_REPROJECT_CURSOR) {
+                                               ED_gp_get_drawing_reference(
+                                                       scene, ob, gpl,
+                                                       ts->gpencil_v3d_align, origin);
+                                       }
+                                       else {
+                                               copy_v3_v3(origin, scene->cursor.location);
+                                       }
 
                                        int axis = 0;
                                        switch (mode) {
@@ -3356,6 +3365,11 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
                                                        axis = 2;
                                                        break;
                                                }
+                                               case GP_REPROJECT_CURSOR:
+                                               {
+                                                       axis = 3;
+                                                       break;
+                                               }
                                                default:
                                                {
                                                        axis = 1;
@@ -3364,8 +3378,8 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
                                        }
 
                                        ED_gp_project_point_to_plane(
-                                               ob, rv3d, origin,
-                                               axis, &pt2);
+                                                       scene, ob, rv3d, origin,
+                                                       axis, &pt2);
 
                                        copy_v3_v3(&pt->x, &pt2.x);
 
@@ -3427,6 +3441,8 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
                 "using 'Cursor' Stroke Placement"},
                {GP_REPROJECT_SURFACE, "SURFACE", 0, "Surface",
                 "Reproject the strokes on to the scene geometry, as if drawn using 'Surface' placement"},
+               {GP_REPROJECT_CURSOR, "CURSOR", 0, "Cursor",
+                "Reproject the strokes using the orienation of 3D cursor"},
                {0, NULL, 0, NULL, NULL},
        };
 
index 7668b7cf5fd5cf3b85a72763f1911d44d534a0a9..36202bdac0a531e1918f8ad39fffba2b58374128 100644 (file)
@@ -132,6 +132,8 @@ typedef struct tGPDfill {
        int fill_simplylvl;
        /** boundary limits drawing mode */
        int fill_draw_mode;
+       /* scaling factor */
+       short fill_factor;
 
        /** number of elements currently in cache */
        short sbuffer_size;
@@ -146,6 +148,13 @@ typedef struct tGPDfill {
        BLI_Stack *stack;
        /** handle for drawing strokes while operator is running 3d stuff */
        void *draw_handle_3d;
+
+       /* tmp size x */
+       int bwinx;
+       /* tmp size y */
+       int bwiny;
+       rcti brect;
+
 } tGPDfill;
 
 
@@ -231,6 +240,7 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
        tgpw.dflag = 0;
        tgpw.disable_fill = 1;
        tgpw.dflag |= (GP_DRAWFILLS_ONLY3D | GP_DRAWFILLS_NOSTATUS);
+       
 
        glEnable(GL_BLEND);
 
@@ -271,23 +281,27 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
                        tgpw.t_gpf = gpf;
 
                        /* reduce thickness to avoid gaps */
-                       tgpw.lthick = gpl->line_change - 4;
+                       tgpw.is_fill_stroke = (tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) ? false : true ;
+                       tgpw.lthick = gpl->line_change;
                        tgpw.opacity = 1.0;
                        copy_v4_v4(tgpw.tintcolor, ink);
                        tgpw.onion = true;
                        tgpw.custonion = true;
 
+                       bool textured_stroke = (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE);
+
                        /* normal strokes */
-                       if ((tgpf->fill_draw_mode == GP_FILL_DMODE_STROKE) ||
-                           (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH))
+                       if (((tgpf->fill_draw_mode == GP_FILL_DMODE_STROKE) ||
+                           (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH)) &&
+                               !textured_stroke)
                        {
                                ED_gp_draw_fill(&tgpw);
-
                        }
 
                        /* 3D Lines with basic shapes and invisible lines */
                        if ((tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) ||
-                           (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH))
+                           (tgpf->fill_draw_mode == GP_FILL_DMODE_BOTH) ||
+                               textured_stroke)
                        {
                                gp_draw_basic_stroke(
                                        tgpf, gps, tgpw.diff_mat, gps->flag & GP_STROKE_CYCLIC, ink,
@@ -300,17 +314,45 @@ static void gp_draw_datablock(tGPDfill *tgpf, const float ink[4])
 }
 
 /* draw strokes in offscreen buffer */
-static void gp_render_offscreen(tGPDfill *tgpf)
+static bool gp_render_offscreen(tGPDfill *tgpf)
 {
        bool is_ortho = false;
        float winmat[4][4];
 
        if (!tgpf->gpd) {
-               return;
+               return false;
        }
+       
+       /* set temporary new size */
+       tgpf->bwinx = tgpf->ar->winx;
+       tgpf->bwiny = tgpf->ar->winy;
+       tgpf->brect = tgpf->ar->winrct;
+
+       /* resize ar */
+       tgpf->ar->winrct.xmin = 0;
+       tgpf->ar->winrct.ymin = 0;
+       tgpf->ar->winrct.xmax = (int)tgpf->ar->winx * tgpf->fill_factor;
+       tgpf->ar->winrct.ymax = (int)tgpf->ar->winy * tgpf->fill_factor;
+       tgpf->ar->winx = (short)abs(tgpf->ar->winrct.xmax - tgpf->ar->winrct.xmin);
+       tgpf->ar->winy = (short)abs(tgpf->ar->winrct.ymax - tgpf->ar->winrct.ymin);
+
+       /* save new size */
+       tgpf->sizex = (int)tgpf->ar->winx;
+       tgpf->sizey = (int)tgpf->ar->winy;
+
+       /* adjust center */
+       float center[2];
+       center[0] = (float)tgpf->center[0] * ((float)tgpf->ar->winx / (float)tgpf->bwinx);
+       center[1] = (float)tgpf->center[1] * ((float)tgpf->ar->winy / (float)tgpf->bwiny);
+       round_v2i_v2fl(tgpf->center, center);
 
        char err_out[256] = "unknown";
        GPUOffScreen *offscreen = GPU_offscreen_create(tgpf->sizex, tgpf->sizey, 0, true, false, err_out);
+       if (offscreen == NULL) {
+               printf("GPencil - Fill - Unable to create fill buffer\n"); 
+               return false;
+       }
+
        GPU_offscreen_bind(offscreen, true);
        uint flag = IB_rect | IB_rectfloat;
        ImBuf *ibuf = IMB_allocImBuf(tgpf->sizex, tgpf->sizey, 32, flag);
@@ -328,18 +370,6 @@ static void gp_render_offscreen(tGPDfill *tgpf)
                perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clip_start, clip_end);
        }
 
-       /* set temporary new size */
-       int bwinx = tgpf->ar->winx;
-       int bwiny = tgpf->ar->winy;
-       rcti brect = tgpf->ar->winrct;
-
-       tgpf->ar->winx = (short)tgpf->sizex;
-       tgpf->ar->winy = (short)tgpf->sizey;
-       tgpf->ar->winrct.xmin = 0;
-       tgpf->ar->winrct.ymin = 0;
-       tgpf->ar->winrct.xmax = tgpf->sizex;
-       tgpf->ar->winrct.ymax = tgpf->sizey;
-
        GPU_matrix_push_projection();
        GPU_matrix_identity_set();
        GPU_matrix_push();
@@ -359,11 +389,6 @@ static void gp_render_offscreen(tGPDfill *tgpf)
        float ink[4] = {1.0f, 0.0f, 0.0f, 1.0f};
        gp_draw_datablock(tgpf, ink);
 
-       /* restore size */
-       tgpf->ar->winx = (short)bwinx;
-       tgpf->ar->winy = (short)bwiny;
-       tgpf->ar->winrct = brect;
-
        GPU_matrix_pop_projection();
        GPU_matrix_pop();
 
@@ -386,6 +411,8 @@ static void gp_render_offscreen(tGPDfill *tgpf)
        /* switch back to window-system-provided framebuffer */
        GPU_offscreen_unbind(offscreen, true);
        GPU_offscreen_free(offscreen);
+
+       return true;
 }
 
 /* return pixel data (rgba) at index */
@@ -459,7 +486,8 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index
                                }
                        }
                        else {
-                               t_a = true; /* edge of image*/
+                               /* edge of image*/
+                               t_a = true;
                                break;
                        }
                }
@@ -474,7 +502,8 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index
                                }
                        }
                        else {
-                               t_b = true; /* edge of image*/
+                               /* edge of image*/
+                               t_b = true;
                                break;
                        }
                }
@@ -543,7 +572,7 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf)
 
        /* calculate index of the seed point using the position of the mouse */
        int index = (tgpf->sizex * tgpf->center[1]) + tgpf->center[0];
-       if ((index >= 0) && (index < maxpixel)) {
+       if ((index >= 0) && (index <= maxpixel)) {
                BLI_stack_push(stack, &index);
        }
 
@@ -561,6 +590,7 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf)
         */
        while (!BLI_stack_is_empty(stack)) {
                int v;
+               
                BLI_stack_pop(stack, &v);
 
                get_pixel(ibuf, v, rgba);
@@ -568,7 +598,7 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf)
                if (true) { /* Was: 'rgba' */
                        /* check if no border(red) or already filled color(green) */
                        if ((rgba[0] != 1.0f) && (rgba[1] != 1.0f)) {
-                               /* fill current pixel */
+                               /* fill current pixel with green */
                                set_pixel(ibuf, v, fill_col);
 
                                /* add contact pixels */
@@ -580,22 +610,22 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf)
                                        }
                                }
                                /* pixel right */
-                               if (v + 1 < maxpixel) {
+                               if (v + 1 <= maxpixel) {
                                        index = v + 1;
                                        if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_HORZ)) {
                                                BLI_stack_push(stack, &index);
                                        }
                                }
                                /* pixel top */
-                               if (v + tgpf->sizex < maxpixel) {
-                                       index = v + tgpf->sizex;
+                               if (v + ibuf->x <= maxpixel) {
+                                       index = v + ibuf->x;
                                        if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
                                                BLI_stack_push(stack, &index);
                                        }
                                }
                                /* pixel bottom */
-                               if (v - tgpf->sizex >= 0) {
-                                       index = v - tgpf->sizex;
+                               if (v - ibuf->x >= 0) {
+                                       index = v - ibuf->x;
                                        if (!is_leak_narrow(ibuf, maxpixel, tgpf->fill_leak, v, LEAK_VERT)) {
                                                BLI_stack_push(stack, &index);
                                        }
@@ -625,7 +655,7 @@ static void gpencil_clean_borders(tGPDfill *tgpf)
        int pixel = 0;
 
        /* horizontal lines */
-       for (idx = 0; idx < ibuf->x - 1; idx++) {
+       for (idx = 0; idx < ibuf->x; idx++) {
                /* bottom line */
                set_pixel(ibuf, idx, fill_col);
                /* top line */
@@ -649,12 +679,117 @@ static void gpencil_clean_borders(tGPDfill *tgpf)
        tgpf->ima->id.tag |= LIB_TAG_DOIT;
 }
 
+/* Naive dilate
+ *
+ * Expand green areas into enclosing red areas.
+ * Using stack prevents creep when replacing colors directly.
+ * -----------
+ *  XXXXXXX
+ *  XoooooX
+ *  XXooXXX
+ *   XXXX
+ * -----------
+ */
+static void dilate(ImBuf *ibuf)
+{
+       BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
+       const float green[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
+       const int maxpixel = (ibuf->x * ibuf->y) - 1;
+       /* detect pixels and expand into red areas */
+       for (int v = maxpixel; v != 0; v--) {
+               float color[4];
+               int index;
+               int tp = 0;
+               int bm = 0;
+               int lt = 0;
+               int rt = 0;
+               get_pixel(ibuf, v, color);
+               if (color[1] == 1.0f) {
+                       /* pixel left */
+                       if (v - 1 >= 0) {
+                               index = v - 1;
+                               get_pixel(ibuf, index, color);
+                               if (color[0] == 1.0f) {
+                                       BLI_stack_push(stack, &index);
+                                       lt = index;
+                               }
+                       }
+                       /* pixel right */
+                       if (v + 1 <= maxpixel) {
+                               index = v + 1;
+                               get_pixel(ibuf, index, color);
+                               if (color[0] == 1.0f) {
+                                       BLI_stack_push(stack, &index);
+                                       rt = index;
+                               }
+                       }
+                       /* pixel top */
+                       if (v + ibuf->x <= maxpixel) {
+                               index = v + ibuf->x;
+                               get_pixel(ibuf, index, color);
+                               if (color[0] == 1.0f) {
+                                       BLI_stack_push(stack, &index);
+                                       tp = index;
+                               }
+                       }
+                       /* pixel bottom */
+                       if (v - ibuf->x >= 0) {
+                               index = v - ibuf->x;
+                               get_pixel(ibuf, index, color);
+                               if (color[0] == 1.0f) {
+                                       BLI_stack_push(stack, &index);
+                                       bm = index;
+                               }
+                       }
+                       /* pixel top-left */
+                       if (tp && lt) {
+                               index = tp - 1;
+                               get_pixel(ibuf, index, color);
+                               if (color[0] == 1.0f) {
+                                       BLI_stack_push(stack, &index);
+                               }
+                       }
+                       /* pixel top-right */
+                       if (tp && rt) {
+                               index = tp + 1;
+                               get_pixel(ibuf, index, color);
+                               if (color[0] == 1.0f) {
+                                       BLI_stack_push(stack, &index);
+                               }
+                       }
+                       /* pixel bottom-left */
+                       if (bm && lt) {
+                               index = bm - 1;
+                               get_pixel(ibuf, index, color);
+                               if (color[0] == 1.0f) {
+                                       BLI_stack_push(stack, &index);
+                               }
+                       }
+                       /* pixel bottom-right */
+                       if (bm && rt) {
+                               index = bm + 1;
+                               get_pixel(ibuf, index, color);
+                               if (color[0] == 1.0f) {
+                                       BLI_stack_push(stack, &index);
+                               }
+                       }
+               }
+       }
+       /* set dilated pixels */
+       while (!BLI_stack_is_empty(stack)) {
+               int v;
+               BLI_stack_pop(stack, &v);
+               set_pixel(ibuf, v, green);
+       }
+       BLI_stack_free(stack);
+}
+
 /* Get the outline points of a shape using Moore Neighborhood algorithm
  *
  * This is a Blender customized version of the general algorithm described
  * in https://en.wikipedia.org/wiki/Moore_neighborhood
  */
-static  void gpencil_get_outline_points(tGPDfill *tgpf)
+static void gpencil_get_outline_points(tGPDfill *tgpf)
 {
        ImBuf *ibuf;
        float rgba[4];
@@ -686,6 +821,9 @@ static  void gpencil_get_outline_points(tGPDfill *tgpf)
        ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
        int imagesize = ibuf->x * ibuf->y;
 
+       /* dilate */
+       dilate(ibuf);
+
        /* find the initial point to start outline analysis */
        for (int idx = imagesize - 1; idx != 0; idx--) {
                get_pixel(ibuf, idx, rgba);
@@ -835,9 +973,9 @@ static void gpencil_points_from_stack(tGPDfill *tgpf)
        while (!BLI_stack_is_empty(tgpf->stack)) {
                int v[2];
                BLI_stack_pop(tgpf->stack, &v);
-               point2D->x = v[0];
-               point2D->y = v[1];
-
+               copy_v2fl_v2i(&point2D->x, v);
+               /* shift points to center of pixel */
+               add_v2_fl(&point2D->x, 0.5f);
                point2D->pressure = 1.0f;
                point2D->strength = 1.0f;
                point2D->time = 0.0f;
@@ -962,7 +1100,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
                        tgpf->scene, tgpf->ob, tgpf->gpl,
                        ts->gpencil_v3d_align, origin);
                ED_gp_project_stroke_to_plane(
-                       tgpf->ob, tgpf->rv3d, gps, origin,
+                       tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin,
                        tgpf->lock_axis - 1);
        }
 
@@ -1076,7 +1214,8 @@ static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op))
        tgpf->fill_threshold = brush->gpencil_settings->fill_threshold;
        tgpf->fill_simplylvl = brush->gpencil_settings->fill_simplylvl;
        tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode;
-
+       tgpf->fill_factor = (short)max_ii(1, min_ii((int)brush->gpencil_settings->fill_factor,8));
+       
        /* get color info */
        Material *ma = BKE_gpencil_get_material_from_brush(brush);
        /* if no brush defaults, get material and color info */
@@ -1238,34 +1377,38 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event)
                                        in_bounds = BLI_rcti_isect_pt(&ar->winrct, event->x, event->y);
 
                                        if ((in_bounds) && (ar->regiontype == RGN_TYPE_WINDOW)) {
+
                                                /* TODO GPXX: Verify the mouse click is right for any window size */
                                                tgpf->center[0] = event->mval[0];
                                                tgpf->center[1] = event->mval[1];
 
-                                               /* save size */
-                                               tgpf->sizex = ar->winx;
-                                               tgpf->sizey = ar->winy;
-
                                                /* render screen to temp image */
-                                               gp_render_offscreen(tgpf);
+                                               if ( gp_render_offscreen(tgpf) ) {
 
-                                               /* apply boundary fill */
-                                               gpencil_boundaryfill_area(tgpf);
+                                                       /* apply boundary fill */
+                                                       gpencil_boundaryfill_area(tgpf);
 
-                                               /* clean borders to avoid infinite loops */
-                                               gpencil_clean_borders(tgpf);
+                                                       /* clean borders to avoid infinite loops */
+                                                       gpencil_clean_borders(tgpf);
 
-                                               /* analyze outline */
-                                               gpencil_get_outline_points(tgpf);
+                                                       /* analyze outline */
+                                                       gpencil_get_outline_points(tgpf);
 
-                                               /* create array of points from stack */
-                                               gpencil_points_from_stack(tgpf);
+                                                       /* create array of points from stack */
+                                                       gpencil_points_from_stack(tgpf);
 
-                                               /* create z-depth array for reproject */
-                                               gpencil_get_depth_array(tgpf);
+                                                       /* create z-depth array for reproject */
+                                                       gpencil_get_depth_array(tgpf);
+
+                                                       /* create stroke and reproject */
+                                                       gpencil_stroke_from_buffer(tgpf);
+
+                                               }
 
-                                               /* create stroke and reproject */
-                                               gpencil_stroke_from_buffer(tgpf);
+                                               /* restore size */
+                                               tgpf->ar->winx = (short)tgpf->bwinx;
+                                               tgpf->ar->winy = (short)tgpf->bwiny;
+                                               tgpf->ar->winrct = tgpf->brect;
 
                                                /* free temp stack data */
                                                if (tgpf->stack) {
index 4fba83a5f02f9ab057e3100d0ed762c722dd331a..aa47319e3d9f3d9b33d2367e305075c03c50720c 100644 (file)
@@ -92,6 +92,7 @@ typedef struct tGPDdraw {
        float tintcolor[4];                 /* tint color */
        bool onion;                         /* onion flag */
        bool custonion;                     /* use custom onion colors */
+       bool is_fill_stroke;              /* use fill tool */
        float diff_mat[4][4];               /* matrix */
 } tGPDdraw;
 
index 99b38098138bc7475841478103605bf2ba4814eb..40f0c0e7b84a73e6d463026bca4216aef0aea50d 100644 (file)
@@ -398,7 +398,9 @@ static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps)
 
        /* get drawing origin */
        gp_get_3d_reference(p, origin);
-       ED_gp_project_stroke_to_plane(obact, rv3d, gps, origin, p->lock_axis - 1);
+       ED_gp_project_stroke_to_plane(
+                                                               p->scene, obact, rv3d, gps,
+                                                               origin, p->lock_axis - 1);
 }
 
 /* convert screen-coordinates to buffer-coordinates */
@@ -752,11 +754,11 @@ static short gp_stroke_addpoint(
                        gp_get_3d_reference(p, origin);
                        /* reproject current */
                        ED_gpencil_tpoint_to_point(p->ar, origin, pt, &spt);
-                       ED_gp_project_point_to_plane(obact, rv3d, origin, p->lock_axis - 1, &spt);
+                       ED_gp_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt);
 
                        /* reproject previous */
                        ED_gpencil_tpoint_to_point(p->ar, origin, ptb, &spt2);
-                       ED_gp_project_point_to_plane(obact, rv3d, origin, p->lock_axis - 1, &spt2);
+                       ED_gp_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2);
                        p->totpixlen += len_v3v3(&spt.x, &spt2.x) / pixsize;
                        pt->uv_fac = p->totpixlen;
                        if ((gp_style) && (gp_style->sima)) {
index 88906488e1a91d6e83f99102928a07ce64b05f7e..962442824f90342858f9c202a3f51dd73f9b7100 100644 (file)
@@ -930,11 +930,13 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
                                ts->gpencil_v3d_align, origin);
                        /* reproject current */
                        ED_gpencil_tpoint_to_point(tgpi->ar, origin, tpt, &spt);
-                       ED_gp_project_point_to_plane(tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt);
+                       ED_gp_project_point_to_plane(tgpi->scene, tgpi->ob, tgpi->rv3d,
+                                                                               origin, tgpi->lock_axis - 1, &spt);
 
                        /* reproject previous */
                        ED_gpencil_tpoint_to_point(tgpi->ar, origin, tptb, &spt2);
-                       ED_gp_project_point_to_plane(tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2);
+                       ED_gp_project_point_to_plane(tgpi->scene, tgpi->ob, tgpi->rv3d,
+                                                                               origin, tgpi->lock_axis - 1, &spt2);
                        tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x) / pixsize;
                        tpt->uv_fac = tgpi->totpixlen;
                        if ((gp_style) && (gp_style->sima)) {
@@ -993,7 +995,8 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
                        tgpi->scene, tgpi->ob, tgpi->gpl,
                        ts->gpencil_v3d_align, origin);
                ED_gp_project_stroke_to_plane(
-                       tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1);
+                               tgpi->scene, tgpi->ob, tgpi->rv3d, gps,
+                               origin, ts->gp_sculpt.lock_axis - 1);
        }
 
        /* if parented change position relative to parent object */
index 84bfd709b10665c0a1f8dc1f1b48b410eadf9752..1605353a156696a8795d962dd4aa023d83691834 100644 (file)
@@ -937,8 +937,12 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *
  * Reproject all points of the stroke to a plane locked to axis to avoid stroke offset
  */
 void ED_gp_project_stroke_to_plane(
-        const Object *ob, const RegionView3D *rv3d, bGPDstroke *gps, const float origin[3], const int axis)
+               const Scene *scene, const Object *ob,
+               const RegionView3D *rv3d, bGPDstroke *gps,
+               const float origin[3], const int axis)
 {
+       const ToolSettings *ts = scene->toolsettings;
+       const View3DCursor *cursor = &scene->cursor;
        float plane_normal[3];
        float vn[3];
 
@@ -953,13 +957,37 @@ void ED_gp_project_stroke_to_plane(
                 */
                ED_view3d_global_to_vector(rv3d, origin, plane_normal);
        }
-       else {
+       else if (axis < 3) {
                plane_normal[axis] = 1.0f;
                /* if object, apply object rotation */
                if (ob && (ob->type == OB_GPENCIL)) {
-                       mul_mat3_m4_v3(ob->obmat, plane_normal);
+                       float mat[4][4];
+                       copy_m4_m4(mat, ob->obmat);
+
+                       /* move origin to cursor */
+                       if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
+                               copy_v3_v3(mat[3], cursor->location);
+                       }
+
+                       mul_mat3_m4_v3(mat, plane_normal);
                }
        }
+       else {
+               float scale[3] = { 1.0f, 1.0f, 1.0f };
+               plane_normal[2] = 1.0f;
+               float mat[4][4];
+               loc_eul_size_to_mat4(mat,
+                       cursor->location,
+                       cursor->rotation_euler,
+                       scale);
+
+               /* move origin to object */
+               if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
+                       copy_v3_v3(mat[3], ob->obmat[3]);
+               }
+
+               mul_mat3_m4_v3(mat, plane_normal);
+       }
 
        /* Reproject the points in the plane */
        for (int i = 0; i < gps->totpoints; i++) {
@@ -984,8 +1012,12 @@ void ED_gp_project_stroke_to_plane(
  * \param[in, out] pt : Point to affect
  */
 void ED_gp_project_point_to_plane(
-        const Object *ob, const RegionView3D *rv3d, const float origin[3], const int axis, bGPDspoint *pt)
+               const Scene *scene, const Object *ob,
+               const RegionView3D *rv3d, const float origin[3],
+               const int axis, bGPDspoint *pt)
 {
+       const ToolSettings *ts = scene->toolsettings;
+       const View3DCursor *cursor = &scene->cursor;
        float plane_normal[3];
        float vn[3];
 
@@ -1000,14 +1032,37 @@ void ED_gp_project_point_to_plane(
                 */
                ED_view3d_global_to_vector(rv3d, origin, plane_normal);
        }
-       else {
+       else if (axis < 3) {
                plane_normal[axis] = 1.0f;
                /* if object, apply object rotation */
                if (ob && (ob->type == OB_GPENCIL)) {
-                       mul_mat3_m4_v3(ob->obmat, plane_normal);
+                       float mat[4][4];
+                       copy_m4_m4(mat, ob->obmat);
+
+                       /* move origin to cursor */
+                       if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
+                               copy_v3_v3(mat[3], cursor->location);
+                       }
+
+                       mul_mat3_m4_v3(mat, plane_normal);
                }
        }
+       else {
+               float scale[3] = { 1.0f, 1.0f, 1.0f };
+               plane_normal[2] = 1.0f;
+               float mat[4][4];
+               loc_eul_size_to_mat4(mat,
+                       cursor->location,
+                       cursor->rotation_euler,
+                       scale);
+
+               /* move origin to object */
+               if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
+                       copy_v3_v3(mat[3], ob->obmat[3]);
+               }
 
+               mul_mat3_m4_v3(mat, plane_normal);
+       }
 
        /* Reproject the points in the plane */
        /* get a vector from the point with the current view direction of the viewport */
index e331032bd6e635027d177d219c1c1627bbe0ff05..fdbb855689108619f90301fbfacd440dcbb583ad 100644 (file)
@@ -225,9 +225,11 @@ void ED_gpencil_add_defaults(struct bContext *C, struct Object *ob);
 void ED_gpencil_setup_modes(struct bContext *C, struct bGPdata *gpd, int newmode);
 
 void ED_gp_project_stroke_to_plane(
+               const struct Scene *scene,
         const struct Object *ob, const struct RegionView3D *rv3d,
         struct bGPDstroke *gps, const float origin[3], const int axis);
 void ED_gp_project_point_to_plane(
+               const struct Scene *scene,
         const struct Object *ob, const struct RegionView3D *rv3d,
         const float origin[3], const int axis, struct bGPDspoint *pt);
 void ED_gp_get_drawing_reference(
index 3de1bd838b32f107b0d12485174fd6321c4657e5..6c7e2d17e061bf8523a873d093566e632512b4c0 100644 (file)
@@ -1,6 +1,9 @@
 uniform mat4 ModelViewProjectionMatrix;
 uniform vec2 Viewport;
 uniform int xraymode;
+uniform int caps_start;
+uniform int caps_end;
+uniform int fill_stroke;
 
 layout(lines_adjacency) in;
 layout(triangle_strip, max_vertices = 13) out;
@@ -15,6 +18,8 @@ out vec2 mTexCoord;
 #define GP_XRAY_3DSPACE 1
 #define GP_XRAY_BACK  2
 
+#define GPENCIL_FLATCAP 1
+
 /* project 3d point to 2d on screen space */
 vec2 toScreenSpace(vec4 vertex)
 {
@@ -37,6 +42,22 @@ float getZdepth(vec4 point)
        /* in front by default */
        return 0.0;
 }
+
+/* check equality but with a small tolerance */
+bool is_equal(vec4 p1, vec4 p2)
+{
+       float limit = 0.0001;
+       float x = abs(p1.x - p2.x);
+       float y = abs(p1.y - p2.y);
+       float z = abs(p1.z - p2.z);
+
+       if ((x < limit) && (y < limit) && (z < limit)) {
+               return true;
+       }
+
+       return false;
+}
+
 void main(void)
 {
        float MiterLimit = 0.75;
@@ -134,10 +155,11 @@ void main(void)
        }
 
        /* generate the start endcap (alpha < 0 used as endcap flag)*/
-       if (P0 == P2) {
+       float extend = (fill_stroke > 0) ? 2 : 1 ;
+       if ((caps_start != GPENCIL_FLATCAP) && is_equal(P0,P2)) {
                mTexCoord = vec2(1, 0.5);
                mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ;
-               vec2 svn1 =  normalize(sp1 - sp2) * length_a * 4.0;
+               vec2 svn1 =  normalize(sp1 - sp2) * length_a * 4.0 * extend;
                gl_Position = vec4((sp1 + svn1) / Viewport, getZdepth(P1), 1.0);
                EmitVertex();
 
@@ -174,7 +196,7 @@ void main(void)
        EmitVertex();
 
        /* generate the end endcap (alpha < 0 used as endcap flag)*/
-       if (P1 == P3) {
+       if ((caps_end != GPENCIL_FLATCAP) && is_equal(P1,P3)) {
                mTexCoord = vec2(0, 1);
                mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ;
                gl_Position = vec4((sp2 + (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0);
@@ -187,7 +209,7 @@ void main(void)
 
                mTexCoord = vec2(1, 0.5);
                mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ;
-               vec2 svn2 =  normalize(sp2 - sp1) * length_b * 4.0;
+               vec2 svn2 =  normalize(sp2 - sp1) * length_b * 4.0 * extend;
                gl_Position = vec4((sp2 + svn2) / Viewport, getZdepth(P2), 1.0);
                EmitVertex();
        }
index 5cbe2f60ebd648ff40f9d89253162da950e7427b..968f913d4e418a44d8969283f515e456eeb45613 100644 (file)
@@ -4,7 +4,7 @@ uniform mat4 ProjectionMatrix;
 uniform float pixsize;   /* rv3d->pixsize */
 uniform int keep_size;
 uniform float objscale;
-uniform int pixfactor;
+uniform float pixfactor;
 
 in vec3 pos;
 in vec4 color;
index 5fec1528e376de9f236f93f80328ba8ad015dea5..4bfbb3655af1677b33cc660c2942188d3e7c6a0a 100644 (file)
@@ -83,23 +83,25 @@ typedef struct BrushGpencilSettings {
        float fill_threshold;
        /** Number of pixel to consider the leak is too small (x 2). */
        short fill_leak;
-       char _pad1[6];
+       /** Fill zoom factor */
+       short fill_factor;
+       char _pad_1[4];
 
        /** Number of simplify steps. */
-       int   fill_simplylvl;
+       int fill_simplylvl;
        /** Type of control lines drawing mode. */
-       int   fill_draw_mode;
+       int fill_draw_mode;
        /** Icon identifier. */
-       int   icon_id;
+       int icon_id;
 
        /** Maximum distance before generate new point for very fast mouse movements. */
-       int   input_samples;
+       int input_samples;
        /** Random factor for UV rotation. */
        float uv_random;
        /** Moved to 'Brush.gpencil_tool'. */
-       int   brush_type DNA_DEPRECATED;
+       int brush_type DNA_DEPRECATED;
        /** Soft, hard or stroke. */
-       int   eraser_mode;
+       int eraser_mode;
        /** Smooth while drawing factor. */
        float active_smooth;
        /** Factor to apply to strength for soft eraser. */
index 711ac8c4bb1d184e30f1e49f911bed28a664ed04..428eb8fbc57512132c92a6e053645217b1186019 100644 (file)
@@ -1053,6 +1053,7 @@ typedef enum eGP_Lockaxis_Types {
        GP_LOCKAXIS_X = 1,
        GP_LOCKAXIS_Y = 2,
        GP_LOCKAXIS_Z = 3,
+       GP_LOCKAXIS_CURSOR = 4
 } eGP_Lockaxis_Types;
 
 /* Settings for a GPencil Stroke Sculpting Brush */
index b14e97b8656fbaf23152801491a9978f7f238d54..86ac8d3bae69b3d4e79757b1f6821ac71e735177 100644 (file)
@@ -126,10 +126,10 @@ static EnumPropertyItem rna_enum_gpencil_brush_eraser_modes_items[] = {
 };
 
 static EnumPropertyItem rna_enum_gpencil_fill_draw_modes_items[] = {
+       {GP_FILL_DMODE_BOTH, "BOTH", 0, "Default", "Use both visible strokes and edit lines as fill boundary limits"},
        {GP_FILL_DMODE_STROKE, "STROKE", 0, "Strokes", "Use visible strokes as fill boundary limits"},
-       {GP_FILL_DMODE_CONTROL, "CONTROL", 0, "Control", "Use internal control lines as fill boundary limits"},
-       {GP_FILL_DMODE_BOTH, "BOTH", 0, "Both", "Use visible strokes and control lines as fill boundary limits"},
-       {0, NULL, 0, NULL, NULL},
+       {GP_FILL_DMODE_CONTROL, "CONTROL", 0, "Edit Lines", "Use edit lines as fill boundary limits"},
+       {0, NULL, 0, NULL, NULL}
 };
 
 static EnumPropertyItem rna_enum_gpencil_brush_icons_items[] = {
@@ -1160,6 +1160,15 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
        RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
        RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
 
+       /* fill factor size */
+       prop = RNA_def_property(srna, "fill_factor", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "fill_factor");
+       RNA_def_property_range(prop, 1, 8);
+       RNA_def_property_ui_text(prop, "Resolution",
+               "Multiplier for fill resolution, higher resolution is more accurate but slower");
+       RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+       RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
+
        /* fill simplify steps */
        prop = RNA_def_property(srna, "fill_simplify_level", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "fill_simplylvl");
index 1393a9d98880ccaa1e3d4b802a1e93c2915b91d5..b66363f45aed3294791b743a94cd46e4c1b6f0ca 100644 (file)
@@ -82,6 +82,7 @@ static const EnumPropertyItem rna_enum_gpencil_lock_axis_items[] = {
        {GP_LOCKAXIS_Y, "AXIS_Y", ICON_AXIS_FRONT, "Front (X-Z)", "Project strokes to plane locked to Y"},
        {GP_LOCKAXIS_X, "AXIS_X", ICON_AXIS_SIDE, "Side (Y-Z)", "Project strokes to plane locked to X"},
        {GP_LOCKAXIS_Z, "AXIS_Z", ICON_AXIS_TOP, "Top (X-Y)", "Project strokes to plane locked to Z"},
+       {GP_LOCKAXIS_CURSOR, "CURSOR", ICON_PIVOT_CURSOR, "Cursor", "Align strokes to current 3D cursor orientation"},
        {0, NULL, 0, NULL, NULL},
 };
 #endif