Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonioya <blendergit@gmail.com>2019-03-17 21:47:31 +0300
committerAntonioya <blendergit@gmail.com>2019-03-17 21:47:56 +0300
commit6577618d5bb93792c805e0c22e4de1a015ee25d5 (patch)
tree05d5056646b3aefd8be21bb1ff314e4373865683 /source/blender/editors/gpencil
parent887d052e56a515145f4dd7433e49c91c5d149169 (diff)
GPencil: Changes in Fill and new 3D Cursor View Plane
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
Diffstat (limited to 'source/blender/editors/gpencil')
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c24
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c56
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c28
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c257
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h1
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c8
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c9
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c67
8 files changed, 356 insertions, 94 deletions
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 1ae3176d393..ebe0fa61b21 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -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 */
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index 0403a42a2c9..2df0edd3bf7 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -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;
+ }
}
}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 1388beb0b20..f14ba3b4f27 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -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},
};
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 7668b7cf5fd..36202bdac0a 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -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) {
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 4fba83a5f02..aa47319e3d9 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -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;
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 99b38098138..40f0c0e7b84 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -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)) {
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 88906488e1a..962442824f9 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -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 */
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 84bfd709b10..1605353a156 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -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 */