diff options
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/gpencil/gpencil_select.c | 43 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_utils.c | 47 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_vertex_paint.c | 43 | ||||
-rw-r--r-- | source/blender/editors/include/ED_gpencil.h | 4 |
4 files changed, 87 insertions, 50 deletions
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 7accf48832a..c41b2993a80 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -68,45 +68,6 @@ /** \name Shared Utilities * \{ */ -/* Check if mouse inside stroke. */ -static bool gpencil_point_inside_stroke(bGPDstroke *gps, - GP_SpaceConversion *gsc, - int mouse[2], - const float diff_mat[4][4]) -{ - bool hit = false; - if (gps->totpoints == 0) { - return hit; - } - - int(*mcoords)[2] = NULL; - int len = gps->totpoints; - mcoords = MEM_mallocN(sizeof(int) * 2 * len, __func__); - - /* Convert stroke to 2D array of points. */ - bGPDspoint *pt; - int i; - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - bGPDspoint pt2; - gp_point_to_parent_space(pt, diff_mat, &pt2); - gp_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]); - } - - /* Compute boundbox of lasso (for faster testing later). */ - rcti rect; - BLI_lasso_boundbox(&rect, mcoords, len); - - /* Test if point inside stroke. */ - hit = ((!ELEM(V2D_IS_CLIPPED, mouse[0], mouse[1])) && - BLI_rcti_isect_pt(&rect, mouse[0], mouse[1]) && - BLI_lasso_is_point_inside(mcoords, len, mouse[0], mouse[1], INT_MAX)); - - /* Free memory. */ - MEM_SAFE_FREE(mcoords); - - return hit; -} - /* Convert sculpt mask mode to Select mode */ static int gpencil_select_mode_from_sculpt(eGP_Sculpt_SelectMaskFlag mode) { @@ -1264,7 +1225,7 @@ static int gpencil_generic_select_exec( mval[0] = (box.xmax + box.xmin) / 2; mval[1] = (box.ymax + box.ymin) / 2; - whole = gpencil_point_inside_stroke(gps_active, &gsc, mval, gpstroke_iter.diff_mat); + whole = ED_gpencil_stroke_point_is_inside(gps_active, &gsc, mval, gpstroke_iter.diff_mat); } /* if stroke mode expand selection. */ @@ -1565,7 +1526,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) { continue; } - bool hit_fill = gpencil_point_inside_stroke(gps, &gsc, mval, gpstroke_iter.diff_mat); + bool hit_fill = ED_gpencil_stroke_point_is_inside(gps, &gsc, mval, gpstroke_iter.diff_mat); if (hit_fill) { hit_stroke = gps_active; hit_point = &gps_active->points[0]; diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 1962eba5017..876fa7c9874 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -31,6 +31,7 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" #include "BLI_hash.h" +#include "BLI_lasso_2d.h" #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_utildefines.h" @@ -2799,3 +2800,49 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, /* Check collision between both rectangles. */ return BLI_rcti_isect(&rect_stroke, &rect_mouse, NULL); } + +/** + * Check if a point is inside of the stroke + * \param gps: Stroke to check + * \param gsc: SpaceConversion data + * \param mouse: Mouse position + * \param diff_mat: View matrix + * \return True if the point is inside + */ +bool ED_gpencil_stroke_point_is_inside(bGPDstroke *gps, + GP_SpaceConversion *gsc, + int mouse[2], + const float diff_mat[4][4]) +{ + bool hit = false; + if (gps->totpoints == 0) { + return hit; + } + + int(*mcoords)[2] = NULL; + int len = gps->totpoints; + mcoords = MEM_mallocN(sizeof(int) * 2 * len, __func__); + + /* Convert stroke to 2D array of points. */ + bGPDspoint *pt; + int i; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + bGPDspoint pt2; + gp_point_to_parent_space(pt, diff_mat, &pt2); + gp_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]); + } + + /* Compute boundbox of lasso (for faster testing later). */ + rcti rect; + BLI_lasso_boundbox(&rect, mcoords, len); + + /* Test if point inside stroke. */ + hit = ((!ELEM(V2D_IS_CLIPPED, mouse[0], mouse[1])) && + BLI_rcti_isect_pt(&rect, mouse[0], mouse[1]) && + BLI_lasso_is_point_inside(mcoords, len, mouse[0], mouse[1], INT_MAX)); + + /* Free memory. */ + MEM_SAFE_FREE(mcoords); + + return hit; +} diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index 10867bd1e0d..581a5d977c2 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -36,6 +36,7 @@ #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_gpencil.h" +#include "BKE_material.h" #include "BKE_report.h" #include "WM_api.h" @@ -433,10 +434,9 @@ static bool brush_tint_apply(tGP_BrushVertexpaintData *gso, CLAMP(inf, 0.0f, 1.0f); CLAMP(inf_fill, 0.0f, 1.0f); - bGPDspoint *pt = &gps->points[pt_index]; - /* Apply color to Stroke point. */ - if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush)) { + if (GPENCIL_TINT_VERTEX_COLOR_STROKE(brush) && (pt_index > -1)) { + bGPDspoint *pt = &gps->points[pt_index]; if (brush_invert_check(gso)) { pt->vert_color[3] -= inf; CLAMP_MIN(pt->vert_color[3], 0.0f); @@ -813,15 +813,18 @@ static void gp_save_selected_point(tGP_BrushVertexpaintData *gso, selected = &gso->pbuffer[gso->pbuffer_used]; selected->gps = gps; selected->pt_index = index; - copy_v2_v2_int(selected->pc, pc); - copy_v4_v4(selected->color, pt->vert_color); - + /* Check the index is not a special case for fill. */ + if (index > -1) { + copy_v2_v2_int(selected->pc, pc); + copy_v4_v4(selected->color, pt->vert_color); + } gso->pbuffer_used++; } /* Select points in this stroke and add to an array to be used later. */ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, bGPDstroke *gps, + const char tool, const float diff_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; @@ -869,6 +872,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, /* Loop over the points in the stroke, checking for intersections * - an intersection means that we touched the stroke */ + bool hit = false; for (i = 0; (i + 1) < gps->totpoints; i++) { /* Get points to work with */ pt1 = gps->points + i; @@ -904,6 +908,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i; if (pt_active != NULL) { + hit = true; gp_save_selected_point(gso, gps_active, index, pc1); } @@ -920,6 +925,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i + 1; if (pt_active != NULL) { + hit = true; gp_save_selected_point(gso, gps_active, index, pc2); include_last = false; } @@ -938,6 +944,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; index = (pt->runtime.pt_orig) ? pt->runtime.idx_orig : i; if (pt_active != NULL) { + hit = true; gp_save_selected_point(gso, gps_active, index, pc1); include_last = false; @@ -945,6 +952,24 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, } } } + + /* If nothing hit, check if the mouse is inside any filled stroke. */ + if ((!hit) && (ELEM(tool, GPAINT_TOOL_TINT, GPVERTEX_TOOL_DRAW))) { + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(gso->object, + gps_active->mat_nr + 1); + if (gp_style->flag & GP_MATERIAL_FILL_SHOW) { + int mval[2]; + round_v2i_v2fl(mval, gso->mval); + bool hit_fill = ED_gpencil_stroke_point_is_inside(gps_active, gsc, mval, diff_mat); + if (hit_fill) { + /* Need repeat the effect because if we don't do that the tint process + * is very slow. */ + for (int repeat = 0; repeat < 50; repeat++) { + gp_save_selected_point(gso, gps_active, -1, NULL); + } + } + } + } } } @@ -956,8 +981,8 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C, const float diff_mat[4][4]) { Object *ob = CTX_data_active_object(C); - char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool : - gso->brush->gpencil_tool; + const char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool : + gso->brush->gpencil_tool; const int radius = (gso->brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure : gso->brush->size; @@ -980,7 +1005,7 @@ static bool gp_vertexpaint_brush_do_frame(bContext *C, } /* Check points below the brush. */ - gp_vertexpaint_select_stroke(gso, gps, diff_mat); + gp_vertexpaint_select_stroke(gso, gps, tool, diff_mat); } /* For Average tool, need calculate the average resulting color from all colors diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 58364e69679..0c228fc962b 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -317,6 +317,10 @@ bool ED_gpencil_stroke_check_collision(struct GP_SpaceConversion *gsc, float mouse[2], const int radius, const float diff_mat[4][4]); +bool ED_gpencil_stroke_point_is_inside(struct bGPDstroke *gps, + struct GP_SpaceConversion *gsc, + int mouse[2], + const float diff_mat[4][4]); #ifdef __cplusplus } |