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:
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt.c')
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c171
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) {