diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint')
12 files changed, 202 insertions, 81 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 892aea6048f..be7b824fc3e 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -875,8 +875,12 @@ static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups, return alpha_overlay_active; } -BLI_INLINE void draw_tri_point( - uint pos, const float sel_col[4], float pivot_col[4], float *co, float width, bool selected) +BLI_INLINE void draw_tri_point(uint pos, + const float sel_col[4], + const float pivot_col[4], + float *co, + float width, + bool selected) { immUniformColor4fv(selected ? sel_col : pivot_col); @@ -905,8 +909,12 @@ BLI_INLINE void draw_tri_point( immEnd(); } -BLI_INLINE void draw_rect_point( - uint pos, const float sel_col[4], float handle_col[4], float *co, float width, bool selected) +BLI_INLINE void draw_rect_point(uint pos, + const float sel_col[4], + const float handle_col[4], + const float *co, + float width, + bool selected) { immUniformColor4fv(selected ? sel_col : handle_col); diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 16ccfaf8286..a7f09390a3d 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -257,7 +257,7 @@ static ushort *brush_painter_mask_ibuf_new(BrushPainter *painter, const int size /* update rectangular section of the brush image */ static void brush_painter_mask_imbuf_update(BrushPainter *painter, ImagePaintTile *tile, - ushort *tex_mask_old, + const ushort *tex_mask_old, int origx, int origy, int w, @@ -1052,7 +1052,7 @@ static void paint_2d_lift_soften(ImagePaintState *s, ImagePaintTile *tile, ImBuf *ibuf, ImBuf *ibufb, - int *pos, + const int *pos, const short paint_tile) { bool sharpen = (tile->cache.invert ^ ((s->brush->flag & BRUSH_DIR_IN) != 0)); @@ -1255,7 +1255,7 @@ static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos, short paint } } -static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos) +static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, const int *pos) { /* note: allocImbuf returns zero'd memory, so regions outside image will * have zero alpha, and hence not be blended onto the image */ diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 83620b4bc56..5af3a3f4241 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -1426,7 +1426,7 @@ static void insert_seam_vert_array(const ProjPaintState *ps, * Be tricky with flags, first 4 bits are #PROJ_FACE_SEAM0 to 4, * last 4 bits are #PROJ_FACE_NOSEAM0 to 4. `1 << i` - where i is `(0..3)`. * - * If we're multithreadng, make sure threads are locked when this is called. + * If we're multi-threading, make sure threads are locked when this is called. */ static void project_face_seams_init(const ProjPaintState *ps, MemArena *arena, @@ -3566,8 +3566,8 @@ static bool project_bucket_face_isect(ProjPaintState *ps, int bucket_y, const MLoopTri *lt) { - /* TODO - replace this with a tricker method that uses sideofline for all - * screenCoords's edges against the closest bucket corner */ + /* TODO - replace this with a trickier method that uses side-of-line for all + * #ProjPaintState.screenCoords edges against the closest bucket corner. */ const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)}; rctf bucket_bounds; float p1[2], p2[2], p3[2], p4[2]; diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index be545600e6e..d65f158174f 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -246,7 +246,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_MODE_TEXTURE_3D, PAINT_MODE_TEXTURE_2D, PAINT_MODE_VERTEX)) { + if (ELEM(mode, + PAINT_MODE_TEXTURE_3D, + PAINT_MODE_TEXTURE_2D, + PAINT_MODE_VERTEX, + PAINT_MODE_SCULPT)) { copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush)); color->value = 0.0; } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c index 048f11c92d7..d05b1673c9a 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.c @@ -206,7 +206,7 @@ void PAINT_OT_vertex_color_from_weight(wmOperatorType *ot) /** \name Smooth Vertex Colors Operator * \{ */ -static void vertex_color_smooth_looptag(Mesh *me, bool *mlooptag) +static void vertex_color_smooth_looptag(Mesh *me, const bool *mlooptag) { const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; const MPoly *mp; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 6d83e88b556..ffdf2c1e7c0 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -547,28 +547,81 @@ void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss) } } -bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index) +static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int index) { - switch (BKE_pbvh_type(ss->pbvh)) { - case PBVH_FACES: { - MeshElemMap *vert_map = &ss->pmap[index]; - int face_set = -1; - for (int i = 0; i < ss->pmap[index].count; i++) { - if (face_set == -1) { - face_set = abs(ss->face_sets[vert_map->indices[i]]); + MeshElemMap *vert_map = &ss->pmap[index]; + int face_set = -1; + for (int i = 0; i < ss->pmap[index].count; i++) { + if (face_set == -1) { + face_set = abs(ss->face_sets[vert_map->indices[i]]); + } + else { + if (abs(ss->face_sets[vert_map->indices[i]]) != face_set) { + return false; + } + } + } + return true; +} + +/** + * Checks if the face sets of the adjacent faces to the edge between \a v1 and \a v2 + * in the base mesh are equal. + */ +static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(SculptSession *ss, int v1, int v2) +{ + MeshElemMap *vert_map = &ss->pmap[v1]; + int p1 = -1, p2 = -1; + for (int i = 0; i < ss->pmap[v1].count; i++) { + MPoly *p = &ss->mpoly[vert_map->indices[i]]; + for (int l = 0; l < p->totloop; l++) { + MLoop *loop = &ss->mloop[p->loopstart + l]; + if (loop->v == v2) { + if (p1 == -1) { + p1 = vert_map->indices[i]; + break; } - else { - if (abs(ss->face_sets[vert_map->indices[i]]) != face_set) { - return false; - } + else if (p2 == -1) { + p2 = vert_map->indices[i]; + break; } } - return true; + } + } + + if (p1 != -1 && p2 != -1) { + return abs(ss->face_sets[p1]) == (ss->face_sets[p2]); + } + return true; +} + +bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index) +{ + switch (BKE_pbvh_type(ss->pbvh)) { + case PBVH_FACES: { + return sculpt_check_unique_face_set_in_base_mesh(ss, index); } case PBVH_BMESH: return false; - case PBVH_GRIDS: - return true; + case PBVH_GRIDS: { + const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); + const int grid_index = index / key->grid_area; + const int vertex_index = index - grid_index * key->grid_area; + const SubdivCCGCoord coord = {.grid_index = grid_index, + .x = vertex_index % key->grid_size, + .y = vertex_index / key->grid_size}; + int v1, v2; + const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get( + ss->subdiv_ccg, &coord, ss->mloop, ss->mpoly, &v1, &v2); + switch (adjacency) { + case SUBDIV_CCG_ADJACENT_VERTEX: + return sculpt_check_unique_face_set_in_base_mesh(ss, v1); + case SUBDIV_CCG_ADJACENT_EDGE: + return sculpt_check_unique_face_set_for_edge_in_base_mesh(ss, v1, v2); + case SUBDIV_CCG_ADJACENT_NONE: + return true; + } + } } return false; } @@ -735,44 +788,64 @@ void SCULPT_vertex_neighbors_get(SculptSession *ss, } } +static bool sculpt_check_boundary_vertex_in_base_mesh(SculptSession *ss, const int index) +{ + const MeshElemMap *vert_map = &ss->pmap[index]; + if (vert_map->count <= 1) { + return true; + } + for (int i = 0; i < vert_map->count; i++) { + const MPoly *p = &ss->mpoly[vert_map->indices[i]]; + unsigned f_adj_v[2]; + if (poly_get_adj_loops_from_vert(p, ss->mloop, index, f_adj_v) != -1) { + int j; + for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) { + if (!(vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2)) { + return true; + } + } + } + } + return false; +} + bool SCULPT_vertex_is_boundary(SculptSession *ss, const int index) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { - const MeshElemMap *vert_map = &ss->pmap[index]; - - if (vert_map->count <= 1) { - return false; - } - if (!SCULPT_vertex_all_face_sets_visible_get(ss, index)) { - return false; - } - - for (int i = 0; i < vert_map->count; i++) { - const MPoly *p = &ss->mpoly[vert_map->indices[i]]; - unsigned f_adj_v[2]; - if (poly_get_adj_loops_from_vert(p, ss->mloop, index, f_adj_v) != -1) { - int j; - for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) { - if (!(vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2)) { - return false; - } - } - } + return true; } - return true; + return sculpt_check_boundary_vertex_in_base_mesh(ss, index); } case PBVH_BMESH: { BMVert *v = BM_vert_at_index(ss->bm, index); return BM_vert_is_boundary(v); } - case PBVH_GRIDS: - return true; + case PBVH_GRIDS: { + const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); + const int grid_index = index / key->grid_area; + const int vertex_index = index - grid_index * key->grid_area; + const SubdivCCGCoord coord = {.grid_index = grid_index, + .x = vertex_index % key->grid_size, + .y = vertex_index / key->grid_size}; + int v1, v2; + const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get( + ss->subdiv_ccg, &coord, ss->mloop, ss->mpoly, &v1, &v2); + switch (adjacency) { + case SUBDIV_CCG_ADJACENT_VERTEX: + return sculpt_check_boundary_vertex_in_base_mesh(ss, v1); + case SUBDIV_CCG_ADJACENT_EDGE: + return sculpt_check_boundary_vertex_in_base_mesh(ss, v1) && + sculpt_check_boundary_vertex_in_base_mesh(ss, v2); + case SUBDIV_CCG_ADJACENT_NONE: + return false; + } + } } - return true; + return false; } /* Utilities */ @@ -2400,7 +2473,10 @@ bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v) } float t[3], bb_min[3], bb_max[3]; - if (data->ignore_fully_masked) { + if (data->ignore_fully_ineffective) { + if (BKE_pbvh_node_fully_hidden_get(node)) { + return false; + } if (BKE_pbvh_node_fully_masked_get(node)) { return false; } @@ -2436,7 +2512,7 @@ bool SCULPT_search_circle_cb(PBVHNode *node, void *data_v) SculptSearchCircleData *data = data_v; float bb_min[3], bb_max[3]; - if (data->ignore_fully_masked) { + if (data->ignore_fully_ineffective) { if (BKE_pbvh_node_fully_masked_get(node)) { return false; } @@ -2489,7 +2565,7 @@ static PBVHNode **sculpt_pbvh_gather_cursor_update(Object *ob, .sd = sd, .radius_squared = ss->cursor_radius, .original = use_original, - .ignore_fully_masked = false, + .ignore_fully_ineffective = false, .center = NULL, }; BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode); @@ -2514,7 +2590,7 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob, .sd = sd, .radius_squared = square_f(ss->cache->radius * radius_scale), .original = use_original, - .ignore_fully_masked = brush->sculpt_tool != SCULPT_TOOL_MASK, + .ignore_fully_ineffective = brush->sculpt_tool != SCULPT_TOOL_MASK, .center = NULL, }; BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode); @@ -2530,7 +2606,7 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob, ss->cursor_radius, .original = use_original, .dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc, - .ignore_fully_masked = brush->sculpt_tool != SCULPT_TOOL_MASK, + .ignore_fully_ineffective = brush->sculpt_tool != SCULPT_TOOL_MASK, }; BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_circle_cb, &data, &nodes, r_totnode); } @@ -5387,11 +5463,15 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe /* Check for unsupported features. */ PBVHType type = BKE_pbvh_type(ss->pbvh); if (brush->sculpt_tool == SCULPT_TOOL_PAINT && type != PBVH_FACES) { - return; + if (!U.experimental.use_sculpt_vertex_colors) { + return; + } } if (brush->sculpt_tool == SCULPT_TOOL_SMEAR && type != PBVH_FACES) { - return; + if (!U.experimental.use_sculpt_vertex_colors) { + return; + } } /* Build a list of all nodes that are potentially within the brush's area of influence */ @@ -5411,7 +5491,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe .sd = sd, .radius_squared = square_f(ss->cache->radius * (1.0 + brush->cloth_sim_limit)), .original = false, - .ignore_fully_masked = false, + .ignore_fully_ineffective = false, .center = ss->cache->initial_location, }; BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode); @@ -6046,6 +6126,14 @@ bool SCULPT_mode_poll(bContext *C) return ob && ob->mode & OB_MODE_SCULPT; } +bool SCULPT_vertex_colors_poll(bContext *C) +{ + if (!U.experimental.use_sculpt_vertex_colors) { + return false; + } + return SCULPT_mode_poll(C); +} + bool SCULPT_mode_poll_view3d(bContext *C) { return (SCULPT_mode_poll(C) && CTX_wm_region_view3d(C)); @@ -8096,7 +8184,7 @@ static void SCULPT_OT_vertex_to_loop_colors(wmOperatorType *ot) ot->idname = "SCULPT_OT_vertex_to_loop_colors"; /* api callbacks */ - ot->poll = SCULPT_mode_poll; + ot->poll = SCULPT_vertex_colors_poll; ot->exec = vertex_to_loop_colors_exec; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8159,7 +8247,7 @@ static void SCULPT_OT_loop_to_vertex_colors(wmOperatorType *ot) ot->idname = "SCULPT_OT_loop_to_vertex_colors"; /* api callbacks */ - ot->poll = SCULPT_mode_poll; + ot->poll = SCULPT_vertex_colors_poll; ot->exec = loop_to_vertex_colors_exec; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8184,7 +8272,6 @@ static int sculpt_sample_color_invoke(bContext *C, copy_v3_v3(color_srgb, active_vertex_color); IMB_colormanagement_scene_linear_to_srgb_v3(color_srgb); BKE_brush_color_set(scene, brush, color_srgb); - BKE_brush_alpha_set(scene, brush, active_vertex_color[3]); WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush); @@ -8200,7 +8287,7 @@ static void SCULPT_OT_sample_color(wmOperatorType *ot) /* api callbacks */ ot->invoke = sculpt_sample_color_invoke; - ot->poll = SCULPT_mode_poll; + ot->poll = SCULPT_vertex_colors_poll; ot->flag = OPTYPE_REGISTER; } @@ -8209,7 +8296,7 @@ static void SCULPT_OT_sample_color(wmOperatorType *ot) /* This allows the sculpt tools to work on meshes with multiple connected components as they had * only one connected component. When initialized and enabled, the sculpt API will return extra * connectivity neighbors that are not in the real mesh. These neighbors are calculated for each - * vertex using the minimun distance to a vertex that is in a different connected component. */ + * vertex using the minimum distance to a vertex that is in a different connected component. */ /* The fake neighbors first need to be ensured to be initialized. * After that tools which needs fake neighbors functionality need to @@ -8224,7 +8311,7 @@ static void SCULPT_OT_sample_color(wmOperatorType *ot) * } * * Such approach allows to keep all the connectivity information ready for reuse - * (withouy having lag prior to every stroke), but also makes it so the affect + * (without having lag prior to every stroke), but also makes it so the affect * is localized to a specific brushes and tools only. */ enum { @@ -8681,6 +8768,11 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); + /* Color data is not available in Multires. */ + if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) { + return OPERATOR_CANCELLED; + } + if (!ss->vcol) { return OPERATOR_CANCELLED; } @@ -8726,12 +8818,12 @@ static void SCULPT_OT_mask_by_color(wmOperatorType *ot) /* api callbacks */ ot->invoke = sculpt_mask_by_color_invoke; - ot->poll = SCULPT_mode_poll; + ot->poll = SCULPT_vertex_colors_poll; ot->flag = OPTYPE_REGISTER; ot->prop = RNA_def_boolean( - ot->srna, "contiguous", false, "Contiguous", "Mask only contiguos color areas"); + ot->srna, "contiguous", false, "Contiguous", "Mask only contiguous color areas"); ot->prop = RNA_def_boolean(ot->srna, "invert", false, "Invert", "Invert the generated mask"); ot->prop = RNA_def_boolean( @@ -8774,6 +8866,7 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_face_sets_init); WM_operatortype_append(SCULPT_OT_cloth_filter); WM_operatortype_append(SCULPT_OT_face_sets_edit); + WM_operatortype_append(SCULPT_OT_sample_color); WM_operatortype_append(SCULPT_OT_loop_to_vertex_colors); WM_operatortype_append(SCULPT_OT_vertex_to_loop_colors); diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index 7c79c1d7a2f..48b278e52b6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -209,7 +209,7 @@ float *SCULPT_boundary_automasking_init(Object *ob, { SculptSession *ss = ob->sculpt; - if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { + if (!ss->pmap) { BLI_assert(!"Boundary Edges masking: pmap missing"); return NULL; } @@ -221,7 +221,7 @@ float *SCULPT_boundary_automasking_init(Object *ob, edge_distance[i] = EDGE_DISTANCE_INF; switch (mode) { case AUTOMASK_INIT_BOUNDARY_EDGES: - if (!SCULPT_vertex_is_boundary(ss, i)) { + if (SCULPT_vertex_is_boundary(ss, i)) { edge_distance[i] = 0; } break; diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 6ca45ee0fb8..6a2137b6626 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -437,13 +437,16 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( BKE_pbvh_vertex_iter_end; } -static void cloth_brush_build_nodes_constraints(Sculpt *sd, - Object *ob, - PBVHNode **nodes, - int totnode, - SculptClothSimulation *cloth_sim, - float initial_location[3], - const float radius) +static void cloth_brush_build_nodes_constraints( + Sculpt *sd, + Object *ob, + PBVHNode **nodes, + int totnode, + SculptClothSimulation *cloth_sim, + /* Cannot be const, because it is assigned to a non-const variable. + * NOLINTNEXTLINE: readability-non-const-parameter. */ + float initial_location[3], + const float radius) { Brush *brush = BKE_paint_brush(&sd->paint); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index 5f7805af347..556b73b0ea5 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -308,7 +308,7 @@ void SCULPT_OT_color_filter(struct wmOperatorType *ot) /* api callbacks */ ot->invoke = sculpt_color_filter_invoke; ot->modal = sculpt_color_filter_modal; - ot->poll = SCULPT_mode_poll; + ot->poll = SCULPT_vertex_colors_poll; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 494588d0996..27dd0ab3e71 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -87,7 +87,7 @@ void SCULPT_filter_cache_init(Object *ob, Sculpt *sd, const int undo_type) .original = true, .center = center, .radius_squared = FLT_MAX, - .ignore_fully_masked = true, + .ignore_fully_ineffective = true, }; BKE_pbvh_search_gather(pbvh, diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index c7e07721eb7..e943bd280a3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -51,6 +51,8 @@ bool SCULPT_mode_poll_view3d(struct bContext *C); bool SCULPT_poll(struct bContext *C); bool SCULPT_poll_view3d(struct bContext *C); +bool SCULPT_vertex_colors_poll(struct bContext *C); + /* Updates */ typedef enum SculptUpdateType { @@ -676,7 +678,8 @@ typedef struct { float radius_squared; const float *center; bool original; - bool ignore_fully_masked; + /* This ignores fully masked and fully hidden nodes. */ + bool ignore_fully_ineffective; } SculptSearchSphereData; typedef struct { @@ -684,7 +687,7 @@ typedef struct { struct SculptSession *ss; float radius_squared; bool original; - bool ignore_fully_masked; + bool ignore_fully_ineffective; struct DistRayAABB_Precalc *dist_ray_to_aabb_precalc; } SculptSearchCircleData; diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c index 5cf6a053382..608ba1b934e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c @@ -388,7 +388,17 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata, float interp_color[4]; copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]); - sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + switch (brush->smear_deform_type) { + case BRUSH_SMEAR_DEFORM_DRAG: + sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + break; + case BRUSH_SMEAR_DEFORM_PINCH: + sub_v3_v3v3(current_disp, ss->cache->location, vd.co); + break; + case BRUSH_SMEAR_DEFORM_EXPAND: + sub_v3_v3v3(current_disp, vd.co, ss->cache->location); + break; + } normalize_v3_v3(current_disp_norm, current_disp); mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); |