diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint')
-rw-r--r-- | source/blender/editors/sculpt_paint/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/SConscript | 5 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_cursor.c | 16 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_curve.c | 18 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image.c | 15 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image_2d.c | 2 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image_proj.c | 146 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_mask.c | 2 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_ops.c | 10 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_stroke.c | 36 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_utils.c | 4 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_vertex.c | 6 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 77 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_uv.c | 5 |
14 files changed, 224 insertions, 120 deletions
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 0fa5f2d9837..46753df4e13 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -23,7 +23,7 @@ set(INC ../uvedit ../../blenkernel ../../blenlib - ../../blenfont + ../../blentranslation ../../bmesh ../../gpu ../../imbuf diff --git a/source/blender/editors/sculpt_paint/SConscript b/source/blender/editors/sculpt_paint/SConscript index 233f562fcc7..52fab472189 100644 --- a/source/blender/editors/sculpt_paint/SConscript +++ b/source/blender/editors/sculpt_paint/SConscript @@ -29,7 +29,8 @@ Import ('env') sources = env.Glob('*.c') -defs = env['BF_GL_DEFINITIONS'] +defs = [] +defs += env['BF_GL_DEFINITIONS'] incs = [ '#/intern/guardedalloc', @@ -37,9 +38,9 @@ incs = [ '#/intern/glew-mx', '../include', '../uvedit', - '../../blenfont', '../../blenkernel', '../../blenlib', + '../../blentranslation', '../../bmesh', '../../gpu', '../../imbuf', diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index e4cad389004..e19756c6a35 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -644,9 +644,9 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush, glMatrixMode(GL_MODELVIEW); glPushMatrix(); if (primary) - glTranslatef(brush->stencil_pos[0], brush->stencil_pos[1], 0); + glTranslate2fv(brush->stencil_pos); else - glTranslatef(brush->mask_stencil_pos[0], brush->mask_stencil_pos[1], 0); + glTranslate2fv(brush->mask_stencil_pos); glRotatef(RAD2DEGF(mtex->rot), 0, 0, 1); glMatrixMode(GL_TEXTURE); } @@ -725,7 +725,7 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush, do_pop = true; glPushMatrix(); glLoadIdentity(); - glTranslatef(center[0], center[1], 0); + glTranslate2fv(center); glScalef(ups->size_pressure_value, ups->size_pressure_value, 1); glTranslatef(-center[0], -center[1], 0); } @@ -756,7 +756,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom, PaintMode mode) { /* color means that primary brush texture is colured and secondary is used for alpha/mask control */ - bool col = ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX) ? true : false; + bool col = ELEM(mode, ePaintTextureProjective, ePaintTexture2D, ePaintVertex) ? true : false; OverlayControlFlags flags = BKE_paint_get_overlay_flags(); /* save lots of GL state * TODO: check on whether all of these are needed? */ @@ -782,7 +782,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom); } else { - if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != PAINT_WEIGHT)) + if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != ePaintWeight)) paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true); if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom); @@ -958,7 +958,7 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewCon static bool ommit_cursor_drawing(Paint *paint, PaintMode mode, Brush *brush) { if (paint->flags & PAINT_SHOW_BRUSH) { - if (ELEM(mode, PAINT_TEXTURE_2D, PAINT_TEXTURE_PROJECTIVE) && brush->imagepaint_tool == PAINT_TOOL_FILL) { + if (ELEM(mode, ePaintTexture2D, ePaintTextureProjective) && brush->imagepaint_tool == PAINT_TOOL_FILL) { return true; } return false; @@ -1014,7 +1014,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* TODO: as sculpt and other paint modes are unified, this * special mode of drawing will go away */ - if ((mode == PAINT_SCULPT) && vc.obact->sculpt) { + if ((mode == ePaintSculpt) && vc.obact->sculpt) { float location[3]; int pixel_radius; bool hit; @@ -1056,7 +1056,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha); /* draw brush outline */ - glTranslatef(translation[0], translation[1], 0); + glTranslate2fv(translation); /* draw an inner brush */ if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) { diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c index ebe5268ec5c..2f27db835f5 100644 --- a/source/blender/editors/sculpt_paint/paint_curve.c +++ b/source/blender/editors/sculpt_paint/paint_curve.c @@ -134,12 +134,12 @@ static void paintcurve_undo_begin(bContext *C, wmOperator *op, PaintCurve *pc) UndoCurve *uc; switch (mode) { - case PAINT_TEXTURE_2D: - case PAINT_TEXTURE_PROJECTIVE: + case ePaintTexture2D: + case ePaintTextureProjective: undo_stack_id = UNDO_PAINT_IMAGE; break; - case PAINT_SCULPT: + case ePaintSculpt: undo_stack_id = UNDO_PAINT_MESH; break; @@ -737,17 +737,17 @@ static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op)) const char *name; switch (mode) { - case PAINT_TEXTURE_2D: - case PAINT_TEXTURE_PROJECTIVE: + case ePaintTexture2D: + case ePaintTextureProjective: name = "PAINT_OT_image_paint"; break; - case PAINT_WEIGHT: + case ePaintWeight: name = "PAINT_OT_weight_paint"; break; - case PAINT_VERTEX: + case ePaintVertex: name = "PAINT_OT_vertex_paint"; break; - case PAINT_SCULPT: + case ePaintSculpt: name = "SCULPT_OT_brush_stroke"; break; default: @@ -777,7 +777,7 @@ static int paintcurve_cursor_invoke(bContext *C, wmOperator *UNUSED(op), const w PaintMode mode = BKE_paintmode_get_active_from_context(C); switch (mode) { - case PAINT_TEXTURE_2D: + case ePaintTexture2D: { ARegion *ar = CTX_wm_region(C); SpaceImage *sima = CTX_wm_space_image(C); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 64e0aa822df..f0c9c023876 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -1045,8 +1045,9 @@ static void toggle_paint_cursor(bContext *C, int enable) * purpose is to make sure the paint cursor is shown if paint * mode is enabled in the image editor. the paint poll will * ensure that the cursor is hidden when not in paint mode */ -void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings) +void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene) { + ToolSettings *settings = scene->toolsettings; wmWindow *win; ScrArea *sa; ImagePaintSettings *imapaint = &settings->imapaint; @@ -1059,7 +1060,7 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings) enabled = true; if (enabled) { - BKE_paint_init(&settings->unified_paint_settings, &imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT); + BKE_paint_init(scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT); paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll); } @@ -1212,7 +1213,7 @@ static int sample_color_exec(bContext *C, wmOperator *op) RNA_int_get_array(op->ptr, "location", location); use_palette = RNA_boolean_get(op->ptr, "palette"); - paint_sample_color(C, ar, location[0], location[1], mode == PAINT_TEXTURE_PROJECTIVE, use_palette); + paint_sample_color(C, ar, location[0], location[1], mode == ePaintTextureProjective, use_palette); if (show_cursor) { paint->flags |= PAINT_SHOW_BRUSH; @@ -1250,7 +1251,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event RNA_int_set_array(op->ptr, "location", event->mval); - paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, false); + paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == ePaintTextureProjective, false); WM_cursor_modal_set(win, BC_EYEDROPPER_CURSOR); WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush); @@ -1289,7 +1290,7 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); RNA_int_set_array(op->ptr, "location", event->mval); - paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, false); + paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == ePaintTextureProjective, false); WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush); break; } @@ -1298,7 +1299,7 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->val == KM_PRESS) { ARegion *ar = CTX_wm_region(C); RNA_int_set_array(op->ptr, "location", event->mval); - paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, true); + paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == ePaintTextureProjective, true); if (!data->sample_palette) { data->sample_palette = true; sample_color_update_header(data, C); @@ -1416,7 +1417,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) ob->mode |= mode_flag; - BKE_paint_init(&scene->toolsettings->unified_paint_settings, &imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT); + BKE_paint_init(scene, ePaintTextureProjective, PAINT_CURSOR_TEXTURE_PAINT); if (U.glreslimit != 0) GPU_free_images(); diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 03a96fb149a..c5a066e9b14 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -1601,6 +1601,7 @@ void paint_2d_gradient_fill( break; } case BRUSH_GRADIENT_RADIAL: + default: { f = len_v2(p) / line_len; break; @@ -1629,6 +1630,7 @@ void paint_2d_gradient_fill( break; } case BRUSH_GRADIENT_RADIAL: + default: { f = len_v2(p) / line_len; break; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index d54db048faf..565f8a51610 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -49,7 +49,7 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "IMB_imbuf.h" @@ -298,6 +298,7 @@ typedef struct ProjPaintState { float cloneOffset[2]; float projectMat[4][4]; /* Projection matrix, use for getting screen coords */ + float projectMatInv[4][4]; /* inverse of projectMat */ float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */ float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */ float clipsta, clipend; @@ -1247,6 +1248,55 @@ static void screen_px_from_persp( } +/** + * Set a direction vector based on a screen location. + * (use for perspective view, else we can simply use `ps->viewDir`) + * + * Similar functionality to #ED_view3d_win_to_vector + * + * \param r_dir: Resulting direction (length is undefined). + */ +static void screen_px_to_vector_persp( + int winx, int winy, const float projmat_inv[4][4], const float view_pos[3], + const float co_px[2], + float r_dir[3]) +{ + r_dir[0] = 2.0f * (co_px[0] / winx) - 1.0f; + r_dir[1] = 2.0f * (co_px[1] / winy) - 1.0f; + r_dir[2] = -0.5f; + mul_project_m4_v3((float(*)[4])projmat_inv, r_dir); + sub_v3_v3(r_dir, view_pos); +} + +/** + * Special function to return the factor to a point along a line in pixel space. + * + * This is needed since we can't use #line_point_factor_v2 for perspective screen-space coords. + * + * \param p: 2D screen-space location. + * \param v1, v2: 3D object-space locations. + */ +static float screen_px_line_point_factor_v2_persp( + const ProjPaintState *ps, + const float p[2], + const float v1[3], const float v2[3]) +{ + const float zero[3] = {0}; + float v1_proj[3], v2_proj[3]; + float dir[3]; + + screen_px_to_vector_persp(ps->winx, ps->winy, ps->projectMatInv, ps->viewPos, p, dir); + + sub_v3_v3v3(v1_proj, v1, ps->viewPos); + sub_v3_v3v3(v2_proj, v2, ps->viewPos); + + project_plane_v3_v3v3(v1_proj, v1_proj, dir); + project_plane_v3_v3v3(v2_proj, v2_proj, dir); + + return line_point_factor_v2(zero, v1_proj, v2_proj); +} + + static void project_face_pixel( const float *lt_tri_uv[3], ImBuf *ibuf_other, const float w[3], unsigned char rgba_ub[4], float rgba_f[4]) @@ -2038,16 +2088,16 @@ static void project_bucket_clip_face( int inside_bucket_flag = 0; int inside_face_flag = 0; int flip; - bool colinear = false; + bool collinear = false; float bucket_bounds_ss[4][2]; - /* detect pathological case where face the three vertices are almost colinear in screen space. + /* detect pathological case where face the three vertices are almost collinear in screen space. * mostly those will be culled but when flood filling or with smooth shading it's a possibility */ if (dist_squared_to_line_v2(v1coSS, v2coSS, v3coSS) < 0.5f || dist_squared_to_line_v2(v2coSS, v3coSS, v1coSS) < 0.5f) { - colinear = true; + collinear = true; } /* get the UV space bounding box */ @@ -2077,7 +2127,7 @@ static void project_bucket_clip_face( return; } /* handle pathological case here, no need for further intersections below since tringle area is almost zero */ - if (colinear) { + if (collinear) { int flag; (*tot) = 0; @@ -2680,8 +2730,15 @@ static void project_paint_face_init( line_clip_rect2f(clip_rect, bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1])) { if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) { /* avoid div by zero */ - fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]); - fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]); + + if (is_ortho) { + fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]); + fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]); + } + else { + fac1 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[0], vCo[fidx1], vCo[fidx2]); + fac2 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[1], vCo[fidx1], vCo[fidx2]); + } interp_v2_v2v2(seam_subsection[0], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac1); interp_v2_v2v2(seam_subsection[1], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac2); @@ -2695,7 +2752,7 @@ static void project_paint_face_init( interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2); - if (pixel_bounds_uv(seam_subsection, &bounds_px, ibuf->x, ibuf->y)) { + if (pixel_bounds_uv((const float (*)[2])seam_subsection, &bounds_px, ibuf->x, ibuf->y)) { /* bounds between the seam rect and the uvspace bucket pixels */ has_isect = 0; @@ -3104,6 +3161,7 @@ static void proj_paint_state_viewport_init( mul_m4_m4m4(ps->projectMat, winmat, vmat); } + invert_m4_m4(ps->projectMatInv, ps->projectMat); /* viewDir - object relative */ copy_m3_m4(mat, viewinv); @@ -3559,34 +3617,6 @@ static bool project_paint_winclip( } #endif //PROJ_DEBUG_WINCLIP -/* Return true if face should be culled, false otherwise */ -static bool project_paint_backface_cull( - const ProjPaintState *ps, const MLoopTri *lt, - const ProjPaintFaceCoSS *coSS) -{ - if (ps->do_backfacecull) { - if (ps->do_mask_normal) { - const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) }; - /* Since we are interpolating the normals of faces, we want to make - * sure all the verts are pointing away from the view, - * not just the face */ - if ((ps->vertFlags[lt_vtri[0]] & PROJ_VERT_CULL) && - (ps->vertFlags[lt_vtri[1]] & PROJ_VERT_CULL) && - (ps->vertFlags[lt_vtri[2]] & PROJ_VERT_CULL)) - { - return true; - } - } - else { - if ((line_point_side_v2(coSS->v1, coSS->v2, coSS->v3) < 0.0f) != ps->is_flip_object) { - return true; - } - - } - } - - return false; -} static void project_paint_build_proj_ima( ProjPaintState *ps, MemArena *arena, @@ -3631,6 +3661,7 @@ static void project_paint_prepare_all_faces( TexPaintSlot *slot = NULL; const MLoopTri *lt; int image_index = -1, tri_index; + int prev_poly = -1; for (tri_index = 0, lt = ps->dm_mlooptri; tri_index < ps->dm_totlooptri; tri_index++, lt++) { bool is_face_sel; @@ -3691,8 +3722,37 @@ static void project_paint_prepare_all_faces( #endif //PROJ_DEBUG_WINCLIP - if (project_paint_backface_cull(ps, lt, &coSS)) { - continue; + /* backface culls individual triangles but mask normal will use polygon */ + if (ps->do_backfacecull) { + if (ps->do_mask_normal) { + if (prev_poly != lt->poly) { + int iloop; + bool culled = true; + const MPoly *poly = ps->dm_mpoly + lt->poly; + int poly_loops = poly->totloop; + prev_poly = lt->poly; + for (iloop = 0; iloop < poly_loops; iloop++) { + if (!(ps->vertFlags[ps->dm_mloop[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) { + culled = false; + break; + } + } + + if (culled) { + /* poly loops - 2 is number of triangles for poly, + * but counter gets incremented when continuing, so decrease by 3 */ + int poly_tri = poly_loops - 3; + tri_index += poly_tri; + lt += poly_tri; + continue; + } + } + } + else { + if ((line_point_side_v2(coSS.v1, coSS.v2, coSS.v3) < 0.0f) != ps->is_flip_object) { + continue; + } + } } } @@ -4264,7 +4324,7 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo } else { premul_float_to_straight_uchar(rgba_ub, rgba); - blend_color_interpolate_byte(rgba_ub, rgba_ub, projPixel->pixel.ch_pt, mask); + blend_color_interpolate_byte(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, mask); } BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); } @@ -4472,6 +4532,7 @@ static void *do_projectpaint_thread(void *ph_v) break; } case BRUSH_GRADIENT_RADIAL: + default: { f = len_v2(p) / line_len; break; @@ -5338,7 +5399,10 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) if (w > maxsize) w = maxsize; if (h > maxsize) h = maxsize; - ibuf = ED_view3d_draw_offscreen_imbuf(scene, CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, false, R_ALPHAPREMUL, NULL, err_out); + ibuf = ED_view3d_draw_offscreen_imbuf( + scene, CTX_wm_view3d(C), CTX_wm_region(C), + w, h, IB_rect, false, R_ALPHAPREMUL, 0, NULL, + NULL, err_out); if (!ibuf) { /* Mostly happens when OpenGL offscreen buffer was failed to create, */ /* but could be other reasons. Should be handled in the future. nazgul */ @@ -5352,7 +5416,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) IMB_freeImBuf(ibuf); if (image) { - /* now for the trickyness. store the view projection here! + /* now for the trickiness. store the view projection here! * re-projection will reuse this */ View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 2254bc991b6..118f3a7571f 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -69,7 +69,7 @@ static EnumPropertyItem mode_items[] = { {PAINT_MASK_FLOOD_VALUE, "VALUE", 0, "Value", "Set mask to the level specified by the 'value' property"}, - {PAINT_MASK_FLOOD_VALUE_INVERSE, "VALUE_INVERSE", 0, "Value Inverted", "Set mask to the level specified by the inverted 'value' property"}, + {PAINT_MASK_FLOOD_VALUE_INVERSE, "VALUE_INVERSE", 0, "Value Inverted", "Set mask to the level specified by the inverted 'value' property"}, {PAINT_MASK_INVERT, "INVERT", 0, "Invert", "Invert the mask"}, {0}}; diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index eebd49895ef..05eda4da63b 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -66,11 +66,12 @@ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op)) Paint *paint = BKE_paint_get_active_from_context(C); Brush *br = BKE_paint_brush(paint); Main *bmain = CTX_data_main(C); + PaintMode mode = BKE_paintmode_get_active_from_context(C); if (br) br = BKE_brush_copy(br); else - br = BKE_brush_add(bmain, "Brush"); + br = BKE_brush_add(bmain, "Brush", BKE_paint_object_mode_from_paint_mode(mode)); BKE_paint_brush_set(paint, br); @@ -201,11 +202,11 @@ static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op)) color = BKE_palette_color_add(palette); palette->active_color = BLI_listbase_count(&palette->colors) - 1; - if (ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX)) { + if (ELEM(mode, ePaintTextureProjective, ePaintTexture2D, ePaintVertex)) { copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush)); color->value = 0.0; } - else if (mode == PAINT_WEIGHT) { + else if (mode == ePaintWeight) { zero_v3(color->rgb); color->value = brush->weight; } @@ -431,9 +432,8 @@ static int brush_generic_tool_set(Main *bmain, Paint *paint, const int tool, brush = brush_tool_cycle(bmain, brush_orig, tool, tool_offset, ob_mode); if (!brush && brush_tool(brush_orig, tool_offset) != tool && create_missing) { - brush = BKE_brush_add(bmain, tool_name); + brush = BKE_brush_add(bmain, tool_name, ob_mode); brush_tool_set(brush, tool_offset, tool); - brush->ob_mode = ob_mode; brush->toggle_brush = brush_orig; } diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index a6d80953178..b1ddf1172c8 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -194,7 +194,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata) static bool paint_tool_require_location(Brush *brush, PaintMode mode) { switch (mode) { - case PAINT_SCULPT: + case ePaintSculpt: if (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB)) { @@ -224,6 +224,7 @@ static bool paint_brush_update(bContext *C, bool location_sampled = false; bool location_success = false; bool do_random = false; + bool do_random_mask = false; /* XXX: Use pressure value from first brush step for brushes which don't * support strokes (grab, thumb). They depends on initial state and * brush coord/pressure/etc. @@ -271,9 +272,11 @@ static bool paint_brush_update(bContext *C, } if (paint_supports_dynamic_tex_coords(brush, mode)) { - if (((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) || - (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) || - (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM))) + + if (ELEM(brush->mtex.brush_map_mode, + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_AREA, + MTEX_MAP_MODE_RANDOM)) { do_random = true; } @@ -286,6 +289,15 @@ static bool paint_brush_update(bContext *C, /* take care of mask texture, if any */ if (brush->mask_mtex.tex) { + + if (ELEM(brush->mask_mtex.brush_map_mode, + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_AREA, + MTEX_MAP_MODE_RANDOM)) + { + do_random_mask = true; + } + if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) BKE_brush_randomize_texture_coords(ups, true); else { @@ -358,7 +370,9 @@ static bool paint_brush_update(bContext *C, ups->brush_rotation += -brush->mtex.random_angle / 2.0f + brush->mtex.random_angle * BLI_frand(); } + } + if (do_random_mask) { if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) { ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f + brush->mask_mtex.random_angle * BLI_frand(); @@ -389,7 +403,7 @@ static bool paint_stroke_use_jitter(PaintMode mode, Brush *brush, bool invert) /* jitter-ed brush gives weird and unpredictable result for this * kinds of stroke, so manually disable jitter usage (sergey) */ use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0; - use_jitter &= (!ELEM(mode, PAINT_TEXTURE_2D, PAINT_TEXTURE_PROJECTIVE) || + use_jitter &= (!ELEM(mode, ePaintTexture2D, ePaintTextureProjective) || !(invert && brush->imagepaint_tool == PAINT_TOOL_CLONE)); @@ -760,13 +774,13 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode) return false; switch (mode) { - case PAINT_SCULPT: + case ePaintSculpt: if (sculpt_is_grab_tool(br)) return false; break; - case PAINT_TEXTURE_2D: /* fall through */ - case PAINT_TEXTURE_PROJECTIVE: + case ePaintTexture2D: /* fall through */ + case ePaintTextureProjective: if ((br->imagepaint_tool == PAINT_TOOL_FILL) && (br->flag & BRUSH_USE_GRADIENT)) { @@ -789,7 +803,7 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode) } switch (mode) { - case PAINT_SCULPT: + case ePaintSculpt: if (sculpt_is_grab_tool(br)) return false; break; @@ -802,7 +816,7 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode) bool paint_supports_texture(PaintMode mode) { /* omit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */ - return ELEM(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D); + return ELEM(mode, ePaintSculpt, ePaintVertex, ePaintTextureProjective, ePaintTexture2D); } /* return true if the brush size can change during paint (normally used for pressure) */ @@ -812,7 +826,7 @@ bool paint_supports_dynamic_tex_coords(Brush *br, PaintMode mode) return false; switch (mode) { - case PAINT_SCULPT: + case ePaintSculpt: if (sculpt_is_grab_tool(br)) return false; break; diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index c76bae01308..7b66632fa42 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -46,7 +46,7 @@ #include "BLI_listbase.h" #include "BLI_rect.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "BKE_brush.h" #include "BKE_context.h" @@ -572,7 +572,7 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot) ot->poll = brush_curve_preset_poll; prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", ""); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ } diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 23f388d2a58..8daad9deea9 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1956,7 +1956,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) paint_cursor_start(C, weight_paint_poll); - BKE_paint_init(&scene->toolsettings->unified_paint_settings, &wp->paint, PAINT_CURSOR_WEIGHT_PAINT); + BKE_paint_init(scene, ePaintWeight, PAINT_CURSOR_WEIGHT_PAINT); /* weight paint specific */ ED_mesh_mirror_spatial_table(ob, NULL, NULL, 's'); @@ -2564,7 +2564,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) paint_cursor_start(C, vertex_paint_poll); - BKE_paint_init(&scene->toolsettings->unified_paint_settings, &vp->paint, PAINT_CURSOR_VERTEX_PAINT); + BKE_paint_init(scene, ePaintVertex, PAINT_CURSOR_VERTEX_PAINT); } /* update modifier stack for mapping requirements */ @@ -2675,7 +2675,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f brush->mtex.tex; /* are we painting onto a modified mesh?, - * if not we can skip face map trickyness */ + * if not we can skip face map trickiness */ if (vertex_paint_use_fast_update_check(ob)) { vpd->use_fast_update = true; /* printf("Fast update!\n");*/ diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index dd10836ef9a..07511e1924e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -41,7 +41,7 @@ #include "BLI_utildefines.h" #include "BLI_ghash.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "DNA_customdata_types.h" #include "DNA_mesh_types.h" @@ -246,6 +246,9 @@ typedef struct StrokeCache { * calc_brush_local_mat() and used in tex_strength(). */ float brush_local_mat[4][4]; + float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */ + int tile_pass; + float last_center[3]; int radial_symmetry_pass; float symm_rot_mat[4][4]; @@ -2501,8 +2504,8 @@ static void calc_sculpt_plane( if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0 && - (ss->cache->first_time || !(brush->flag & BRUSH_ORIGINAL_NORMAL) || - (sd->paint.symmetry_flags & PAINT_TILE_AXIS_ALL))) + ss->cache->tile_pass == 0 && + (ss->cache->first_time || !(brush->flag & BRUSH_ORIGINAL_NORMAL))) { switch (brush->sculpt_plane) { case SCULPT_DISP_DIR_VIEW: @@ -2558,6 +2561,9 @@ static void calc_sculpt_plane( /* for flatten center */ mul_m4_v3(ss->cache->symm_rot_mat, r_area_co); + + /* shift the plane for the current tile */ + add_v3_v3(r_area_co, ss->cache->plane_offset); } } @@ -3438,6 +3444,7 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm, unit_m4(cache->symm_rot_mat); unit_m4(cache->symm_rot_mat_inv); + zero_v3(cache->plane_offset); if (axis) { /* expects XYZ */ rotate_m4(cache->symm_rot_mat, axis, angle); @@ -3462,37 +3469,48 @@ static void do_tiled(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings const float radius = cache->radius; const float *bbMin = ob->bb->vec[0]; const float *bbMax = ob->bb->vec[6]; - - float start[3]; - float end[3]; const float *step = sd->paint.tile_offset; int dim; + /* These are integer locations, for real location: multiply with step and add orgLoc. So 0,0,0 is at orgLoc. */ + int start[3]; + int end[3]; + int cur[3]; + + float orgLoc[3]; /* position of the "prototype" stroke for tiling */ + copy_v3_v3(orgLoc, cache->location); + for (dim = 0; dim < 3; ++dim) { if ((sd->paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) { - int n = (cache->location[dim] - bbMin[dim] + radius) / step[dim]; - start[dim] = cache->location[dim] - n * step[dim]; - end[dim] = bbMax[dim] + radius; + start[dim] = (bbMin[dim] - orgLoc[dim] - radius) / step[dim]; + end[dim] = (bbMax[dim] - orgLoc[dim] + radius) / step[dim]; } else - start[dim] = end[dim] = cache->location[dim]; + start[dim] = end[dim] = 0; } - copy_v3_v3(cache->location, start); - do { - do { - do { - action(sd, ob, brush, ups); - cache->location[2] += step[2]; - } while (cache->location[2] < end[2]); - cache->location[2] = start[2]; + /* first do the "untiled" position to initialize the stroke for this location */ + cache->tile_pass = 0; + action(sd, ob, brush, ups); + + /* now do it for all the tiles */ + copy_v3_v3_int(cur, start); + for (cur[0] = start[0]; cur[0] <= end[0]; ++cur[0]) { + for (cur[1] = start[1]; cur[1] <= end[1]; ++cur[1]) { + for (cur[2] = start[2]; cur[2] <= end[2]; ++cur[2]) { + if (!cur[0] && !cur[1] && !cur[2]) + continue; /* skip tile at orgLoc, this was already handled before all others */ - cache->location[1] += step[1]; - } while (cache->location[1] < end[1]); - cache->location[1] = start[1]; + ++cache->tile_pass; - cache->location[0] += step[0]; - } while (cache->location[0] < end[0]); + for (dim = 0; dim < 3; ++dim) { + cache->location[dim] = cur[dim] * step[dim] + orgLoc[dim]; + cache->plane_offset[dim] = cur[dim] * step[dim]; + } + action(sd, ob, brush, ups); + } + } + } } @@ -4044,7 +4062,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, * brush coord/pressure/etc. * It's more an events design issue, which doesn't split coordinate/pressure/angle * changing events. We should avoid this after events system re-design */ - if (paint_supports_dynamic_size(brush, PAINT_SCULPT) || cache->first_time) { + if (paint_supports_dynamic_size(brush, ePaintSculpt) || cache->first_time) { cache->pressure = RNA_float_get(ptr, "pressure"); } @@ -4061,7 +4079,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, } } - if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, PAINT_SCULPT)) { + if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, ePaintSculpt)) { cache->radius = cache->initial_radius * cache->pressure; } else { @@ -4199,7 +4217,10 @@ static float sculpt_raycast_init(ViewContext *vc, const float mouse[2], float ra sub_v3_v3v3(ray_normal, ray_end, ray_start); dist = normalize_v3(ray_normal); - if (!rv3d->is_persp) { + if ((rv3d->is_persp == false) && + /* if the ray is clipped, don't adjust its start/end */ + ((rv3d->rflag & RV3D_CLIPPING) == 0)) + { BKE_pbvh_raycast_project_ray_root(ob->sculpt->pbvh, original, ray_start, ray_end, ray_normal); /* recalculate the normal */ @@ -4879,7 +4900,7 @@ static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, co if (!ELEM(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX) && (CustomData_has_layer(&me->vdata, i) || CustomData_has_layer(&me->edata, i) || - CustomData_has_layer(&me->fdata, i))) + CustomData_has_layer(&me->ldata, i))) { vdata = true; break; @@ -5123,7 +5144,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) "Object has negative scale, sculpting may be unpredictable"); } - BKE_paint_init(&ts->unified_paint_settings, &ts->sculpt->paint, PAINT_CURSOR_SCULPT); + BKE_paint_init(scene, ePaintSculpt, PAINT_CURSOR_SCULPT); paint_cursor_start(C, sculpt_poll_view3d); } diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index e01d8a6bd17..405ac3f6808 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -224,8 +224,9 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu } -void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings) +void ED_space_image_uv_sculpt_update(wmWindowManager *wm, Scene *scene) { + ToolSettings *settings = scene->toolsettings; if (settings->use_uv_sculpt) { if (!settings->uvsculpt) { settings->uvsculpt = MEM_callocN(sizeof(*settings->uvsculpt), "UV Smooth paint"); @@ -236,7 +237,7 @@ void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings settings->uvsculpt->paint.flags |= PAINT_SHOW_BRUSH; } - BKE_paint_init(&settings->unified_paint_settings, &settings->uvsculpt->paint, PAINT_CURSOR_SCULPT); + BKE_paint_init(scene, ePaintSculptUV, PAINT_CURSOR_SCULPT); settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(wm, uv_sculpt_brush_poll, brush_drawcursor_uvsculpt, NULL); |