diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 171 |
1 files changed, 112 insertions, 59 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 32b7047c2b0..9ce80e4a433 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -148,7 +148,7 @@ const float *SCULPT_vertex_co_get(SculptSession *ss, int index) bool SCULPT_has_loop_colors(const Object *ob) { Mesh *me = BKE_object_get_original_mesh(ob); - CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); + const CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); return layer && BKE_id_attribute_domain(&me->id, layer) == ATTR_DOMAIN_CORNER; } @@ -1354,8 +1354,23 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, SculptSession *ss = data->ob->sculpt; SculptUndoNode *unode; - SculptUndoType type = (data->brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : - SCULPT_UNDO_COORDS); + SculptUndoType type; + + switch (data->brush->sculpt_tool) { + case SCULPT_TOOL_MASK: + type = SCULPT_UNDO_MASK; + BKE_pbvh_node_mark_update_mask(data->nodes[n]); + break; + case SCULPT_TOOL_PAINT: + case SCULPT_TOOL_SMEAR: + type = SCULPT_UNDO_COLOR; + BKE_pbvh_node_mark_update_color(data->nodes[n]); + break; + default: + type = SCULPT_UNDO_COORDS; + BKE_pbvh_node_mark_update(data->nodes[n]); + break; + } if (ss->bm) { unode = SCULPT_undo_push_node(data->ob, data->nodes[n], type); @@ -1397,8 +1412,6 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, } } BKE_pbvh_vertex_iter_end; - - BKE_pbvh_node_mark_update(data->nodes[n]); } static void paint_mesh_restore_co(Sculpt *sd, Object *ob) @@ -3248,8 +3261,8 @@ static void do_brush_action(Sculpt *sd, } nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode); } - - if (sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob)) { + const bool use_pixels = sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob); + if (use_pixels) { sculpt_pbvh_update_pixels(paint_mode_settings, ss, ob); } @@ -3302,16 +3315,18 @@ static void do_brush_action(Sculpt *sd, } float location[3]; - SculptThreadedTaskData task_data = { - .sd = sd, - .ob = ob, - .brush = brush, - .nodes = nodes, - }; + if (!use_pixels) { + SculptThreadedTaskData task_data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); + } if (sculpt_brush_needs_normal(ss, brush)) { update_sculpt_normal(sd, ob, nodes, totnode); @@ -3520,15 +3535,7 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata, SculptSession *ss = data->ob->sculpt; Sculpt *sd = data->sd; Object *ob = data->ob; - - /* These brushes start from original coordinates. */ - const bool use_orco = ELEM(data->brush->sculpt_tool, - SCULPT_TOOL_GRAB, - SCULPT_TOOL_ROTATE, - SCULPT_TOOL_THUMB, - SCULPT_TOOL_ELASTIC_DEFORM, - SCULPT_TOOL_BOUNDARY, - SCULPT_TOOL_POSE); + const bool use_orco = data->use_proxies_orco; PBVHVertexIter vd; PBVHProxyNode *proxies; @@ -3583,12 +3590,23 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) return; } + /* First line is tools that don't support proxies. */ + const bool use_orco = ELEM(brush->sculpt_tool, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_ELASTIC_DEFORM, + SCULPT_TOOL_BOUNDARY, + SCULPT_TOOL_POSE); + BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); + SculptThreadedTaskData data = { .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, + .use_proxies_orco = use_orco, }; TaskParallelSettings settings; @@ -3597,6 +3615,27 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) MEM_SAFE_FREE(nodes); } +void SCULPT_combine_transform_proxies(Sculpt *sd, Object *ob) +{ + SculptSession *ss = ob->sculpt; + PBVHNode **nodes; + int totnode; + + BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .nodes = nodes, + .use_proxies_orco = false, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); + + MEM_SAFE_FREE(nodes); +} + /** * Copy the modified vertices from the #PBVH to the active key. */ @@ -4135,7 +4174,7 @@ static void smooth_brush_toggle_off(const bContext *C, Paint *paint, StrokeCache /* Initialize the stroke cache invariants from operator properties. */ static void sculpt_update_cache_invariants( - bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2]) + bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mval[2]) { StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache"); UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; @@ -4165,8 +4204,8 @@ static void sculpt_update_cache_invariants( sculpt_init_mirror_clipping(ob, ss); /* Initial mouse location. */ - if (mouse) { - copy_v2_v2(cache->initial_mouse, mouse); + if (mval) { + copy_v2_v2(cache->initial_mouse, mval); } else { zero_v2(cache->initial_mouse); @@ -4304,7 +4343,8 @@ static bool sculpt_needs_delta_from_anchored_origin(Brush *brush) SCULPT_TOOL_POSE, SCULPT_TOOL_BOUNDARY, SCULPT_TOOL_THUMB, - SCULPT_TOOL_ELASTIC_DEFORM)) { + SCULPT_TOOL_ELASTIC_DEFORM, + SCULPT_TOOL_SMEAR)) { return true; } if (brush->sculpt_tool == SCULPT_TOOL_CLOTH && @@ -4334,7 +4374,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru { SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; - const float mouse[2] = { + const float mval[2] = { cache->mouse_event[0], cache->mouse_event[1], }; @@ -4353,6 +4393,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_POSE, SCULPT_TOOL_BOUNDARY, + SCULPT_TOOL_SMEAR, SCULPT_TOOL_THUMB) && !sculpt_brush_use_topology_rake(ss, brush)) { return; @@ -4374,9 +4415,9 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru add_v3_v3(cache->true_location, cache->grab_delta); } - /* Compute 3d coordinate at same z from original location + mouse. */ + /* Compute 3d coordinate at same z from original location + mval. */ mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location); - ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mouse, grab_location); + ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mval, grab_location); /* Compute delta to move verts by. */ if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { @@ -4744,7 +4785,7 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *t } float SCULPT_raycast_init(ViewContext *vc, - const float mouse[2], + const float mval[2], float ray_start[3], float ray_end[3], float ray_normal[3], @@ -4758,7 +4799,7 @@ float SCULPT_raycast_init(ViewContext *vc, /* TODO: what if the segment is totally clipped? (return == 0). */ ED_view3d_win_to_segment_clipped( - vc->depsgraph, vc->region, vc->v3d, mouse, ray_start, ray_end, true); + vc->depsgraph, vc->region, vc->v3d, mval, ray_start, ray_end, true); invert_m4_m4(obimat, ob->obmat); mul_m4_v3(obimat, ray_start); @@ -4782,7 +4823,7 @@ float SCULPT_raycast_init(ViewContext *vc, bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, - const float mouse[2], + const float mval[2], bool use_sampled_normal) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); @@ -4811,7 +4852,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C, } /* PBVH raycast to get active vertex and face normal. */ - depth = SCULPT_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original); + depth = SCULPT_raycast_init(&vc, mval, ray_start, ray_end, ray_normal, original); SCULPT_stroke_modifiers_check(C, ob, brush); SculptRaycastData srd = { @@ -4909,7 +4950,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C, return true; } -bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2]) +bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mval[2]) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Object *ob; @@ -4931,7 +4972,7 @@ bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2]) SCULPT_stroke_modifiers_check(C, ob, brush); - depth = SCULPT_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original); + depth = SCULPT_raycast_init(&vc, mval, ray_start, ray_end, ray_normal, original); if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { BM_mesh_elem_table_ensure(ss->bm, BM_VERT); @@ -5236,14 +5277,10 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up /* Returns whether the mouse/stylus is over the mesh (1) * or over the background (0). */ -static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), float x, float y) +static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), const float mval[2]) { - float mouse[2], co[3]; - - mouse[0] = x; - mouse[1] = y; - - return SCULPT_stroke_get_location(C, co, mouse); + float co_dummy[3]; + return SCULPT_stroke_get_location(C, co_dummy, mval); } bool SCULPT_handles_colors_report(SculptSession *ss, ReportList *reports) @@ -5264,36 +5301,44 @@ bool SCULPT_handles_colors_report(SculptSession *ss, ReportList *reports) return false; } -static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2]) +static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mval[2]) { - /* Don't start the stroke until mouse goes over the mesh. - * NOTE: mouse will only be null when re-executing the saved stroke. - * We have exception for 'exec' strokes since they may not set 'mouse', + /* Don't start the stroke until `mval` goes over the mesh. + * NOTE: `mval` will only be null when re-executing the saved stroke. + * We have exception for 'exec' strokes since they may not set `mval`, * only 'location', see: T52195. */ - if (((op->flag & OP_IS_INVOKE) == 0) || (mouse == NULL) || - over_mesh(C, op, mouse[0], mouse[1])) { + if (((op->flag & OP_IS_INVOKE) == 0) || (mval == NULL) || over_mesh(C, op, mval)) { Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); + ToolSettings *tool_settings = CTX_data_tool_settings(C); /* NOTE: This should be removed when paint mode is available. Paint mode can force based on the * canvas it is painting on. (ref. use_sculpt_texture_paint). */ if (brush && SCULPT_TOOL_NEEDS_COLOR(brush->sculpt_tool)) { View3D *v3d = CTX_wm_view3d(C); - if (v3d) { + if (v3d->shading.type == OB_SOLID) { v3d->shading.color_type = V3D_SHADING_VERTEX_COLOR; } } ED_view3d_init_mats_rv3d(ob, CTX_wm_region_view3d(C)); - sculpt_update_cache_invariants(C, sd, ss, op, mouse); + sculpt_update_cache_invariants(C, sd, ss, op, mval); SculptCursorGeometryInfo sgi; - SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); + SCULPT_cursor_geometry_info_update(C, &sgi, mval, false); - SCULPT_undo_push_begin(ob, sculpt_tool_name(sd)); + /* Setup the correct undo system. Image painting and sculpting are mutual exclusive. + * Color attributes are part of the sculpting undo system. */ + if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT && + SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) { + ED_image_undo_push_begin(op->type->name, PAINT_MODE_SCULPT); + } + else { + SCULPT_undo_push_begin(ob, sculpt_tool_name(sd)); + } return true; } @@ -5420,7 +5465,13 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str SCULPT_cache_free(ss->cache); ss->cache = NULL; - SCULPT_undo_push_end(ob); + if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT && + SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) { + ED_image_undo_push_end(); + } + else { + SCULPT_undo_push_end(ob); + } if (brush->sculpt_tool == SCULPT_TOOL_MASK) { SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); @@ -5469,7 +5520,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent /* For tablet rotation. */ ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click"); - if (ignore_background_click && !over_mesh(C, op, event->xy[0], event->xy[1])) { + if (ignore_background_click && !over_mesh(C, op, (const float[2]){UNPACK2(event->mval)})) { paint_stroke_free(C, op, op->customdata); return OPERATOR_PASS_THROUGH; } @@ -5729,7 +5780,8 @@ void SCULPT_connected_components_ensure(Object *ob) { SculptSession *ss = ob->sculpt; - /* Topology IDs already initialized. They only need to be recalculated when the PBVH is rebuild. + /* Topology IDs already initialized. They only need to be recalculated when the PBVH is + * rebuild. */ if (ss->vertex_info.connected_component) { return; @@ -5793,7 +5845,8 @@ void SCULPT_fake_neighbors_ensure(Sculpt *sd, Object *ob, const float max_dist) SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); - /* Fake neighbors were already initialized with the same distance, so no need to be recalculated. + /* Fake neighbors were already initialized with the same distance, so no need to be + * recalculated. */ if (ss->fake_neighbors.fake_neighbor_index && ss->fake_neighbors.current_max_distance == max_dist) { |