Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/sculpt_paint/sculpt.c
| Show First 20 Lines • Show All 1,393 Lines • ▼ Show 20 Lines | if (orig_data->bm_log) { | ||||
| orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert); | orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert); | ||||
| } | } | ||||
| else { | else { | ||||
| orig_data->mask = orig_data->vmasks[iter->i]; | orig_data->mask = orig_data->vmasks[iter->i]; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void SCULPT_orig_face_data_unode_init(SculptOrigFaceData *data, Object *ob, SculptUndoNode *unode) | |||||
| { | |||||
| SculptSession *ss = ob->sculpt; | |||||
| BMesh *bm = ss->bm; | |||||
| memset(data, 0, sizeof(*data)); | |||||
| data->unode = unode; | |||||
| if (bm) { | |||||
| data->bm_log = ss->bm_log; | |||||
| } | |||||
| else { | |||||
| data->face_sets = unode->face_sets; | |||||
| } | |||||
| } | |||||
| void SCULPT_orig_face_data_init(SculptOrigFaceData *data, | |||||
| Object *ob, | |||||
| PBVHNode *node, | |||||
| SculptUndoType type) | |||||
| { | |||||
| SculptUndoNode *unode; | |||||
| unode = SCULPT_undo_push_node(ob, node, type); | |||||
| SCULPT_orig_face_data_unode_init(data, ob, unode); | |||||
| } | |||||
| void SCULPT_orig_face_data_update(SculptOrigFaceData *orig_data, PBVHFaceIter *iter) | |||||
| { | |||||
| if (orig_data->unode->type == SCULPT_UNDO_FACE_SETS) { | |||||
| orig_data->face_set = orig_data->face_sets ? orig_data->face_sets[iter->i] : false; | |||||
| } | |||||
| } | |||||
| static void sculpt_rake_data_update(struct SculptRakeData *srd, const float co[3]) | static void sculpt_rake_data_update(struct SculptRakeData *srd, const float co[3]) | ||||
| { | { | ||||
| float rake_dist = len_v3v3(srd->follow_co, co); | float rake_dist = len_v3v3(srd->follow_co, co); | ||||
| if (rake_dist > srd->follow_dist) { | if (rake_dist > srd->follow_dist) { | ||||
| interp_v3_v3v3(srd->follow_co, srd->follow_co, co, rake_dist - srd->follow_dist); | interp_v3_v3v3(srd->follow_co, srd->follow_co, co, rake_dist - srd->follow_dist); | ||||
| } | } | ||||
| } | } | ||||
| Show All 35 Lines | static void paint_mesh_restore_co_task_cb(void *__restrict userdata, | ||||
| switch (data->brush->sculpt_tool) { | switch (data->brush->sculpt_tool) { | ||||
| case SCULPT_TOOL_MASK: | case SCULPT_TOOL_MASK: | ||||
| type = SCULPT_UNDO_MASK; | type = SCULPT_UNDO_MASK; | ||||
| break; | break; | ||||
| case SCULPT_TOOL_PAINT: | case SCULPT_TOOL_PAINT: | ||||
| case SCULPT_TOOL_SMEAR: | case SCULPT_TOOL_SMEAR: | ||||
| type = SCULPT_UNDO_COLOR; | type = SCULPT_UNDO_COLOR; | ||||
| break; | break; | ||||
| case SCULPT_TOOL_DRAW_FACE_SETS: | |||||
| type = ss->cache->alt_smooth ? SCULPT_UNDO_COORDS : SCULPT_UNDO_FACE_SETS; | |||||
| break; | |||||
| default: | default: | ||||
| type = SCULPT_UNDO_COORDS; | type = SCULPT_UNDO_COORDS; | ||||
| break; | break; | ||||
| } | } | ||||
| if (ss->bm) { | if (ss->bm) { | ||||
| unode = SCULPT_undo_push_node(data->ob, data->nodes[n], type); | unode = SCULPT_undo_push_node(data->ob, data->nodes[n], type); | ||||
| } | } | ||||
| else { | else { | ||||
| unode = SCULPT_undo_get_node(data->nodes[n], type); | unode = SCULPT_undo_get_node(data->nodes[n], type); | ||||
| } | } | ||||
| if (!unode) { | if (!unode) { | ||||
| return; | return; | ||||
| } | } | ||||
| switch (type) { | switch (type) { | ||||
| case SCULPT_UNDO_MASK: | case SCULPT_UNDO_MASK: | ||||
| BKE_pbvh_node_mark_update_mask(data->nodes[n]); | BKE_pbvh_node_mark_update_mask(data->nodes[n]); | ||||
| break; | break; | ||||
| case SCULPT_UNDO_COLOR: | case SCULPT_UNDO_COLOR: | ||||
| BKE_pbvh_node_mark_update_color(data->nodes[n]); | BKE_pbvh_node_mark_update_color(data->nodes[n]); | ||||
| break; | break; | ||||
| case SCULPT_UNDO_FACE_SETS: | |||||
| BKE_pbvh_node_mark_update_face_sets(data->nodes[n]); | |||||
| break; | |||||
| case SCULPT_UNDO_COORDS: | case SCULPT_UNDO_COORDS: | ||||
| BKE_pbvh_node_mark_update(data->nodes[n]); | BKE_pbvh_node_mark_update(data->nodes[n]); | ||||
| break; | break; | ||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| PBVHVertexIter vd; | PBVHVertexIter vd; | ||||
| SculptOrigVertData orig_data; | SculptOrigVertData orig_vert_data; | ||||
| SculptOrigFaceData orig_face_data; | |||||
| if (type != SCULPT_UNDO_FACE_SETS) { | |||||
| SCULPT_orig_vert_data_unode_init(&orig_vert_data, data->ob, unode); | |||||
| } | |||||
| else { | |||||
| SCULPT_orig_face_data_unode_init(&orig_face_data, data->ob, unode); | |||||
| } | |||||
| if (unode->type == SCULPT_UNDO_FACE_SETS) { | |||||
| PBVHFaceIter fd; | |||||
| BKE_pbvh_face_iter_begin (ss->pbvh, data->nodes[n], fd) { | |||||
| SCULPT_orig_face_data_update(&orig_face_data, &fd); | |||||
| if (fd.face_set) { | |||||
| *fd.face_set = orig_face_data.face_set; | |||||
| } | |||||
| } | |||||
| SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode); | BKE_pbvh_face_iter_end(fd); | ||||
| return; | |||||
| } | |||||
| BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { | BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { | ||||
| SCULPT_orig_vert_data_update(&orig_data, &vd); | SCULPT_orig_vert_data_update(&orig_vert_data, &vd); | ||||
| if (orig_data.unode->type == SCULPT_UNDO_COORDS) { | if (orig_vert_data.unode->type == SCULPT_UNDO_COORDS) { | ||||
| copy_v3_v3(vd.co, orig_data.co); | copy_v3_v3(vd.co, orig_vert_data.co); | ||||
| if (vd.no) { | if (vd.no) { | ||||
| copy_v3_v3(vd.no, orig_data.no); | copy_v3_v3(vd.no, orig_vert_data.no); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v3_v3(vd.fno, orig_data.no); | copy_v3_v3(vd.fno, orig_vert_data.no); | ||||
| } | } | ||||
| if (vd.mvert) { | if (vd.mvert) { | ||||
| BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); | BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); | ||||
| } | } | ||||
| } | } | ||||
| else if (orig_data.unode->type == SCULPT_UNDO_MASK) { | else if (orig_vert_data.unode->type == SCULPT_UNDO_MASK) { | ||||
| *vd.mask = orig_data.mask; | *vd.mask = orig_vert_data.mask; | ||||
| } | } | ||||
| else if (orig_data.unode->type == SCULPT_UNDO_COLOR) { | else if (orig_vert_data.unode->type == SCULPT_UNDO_COLOR) { | ||||
| SCULPT_vertex_color_set(ss, vd.vertex, orig_data.col); | SCULPT_vertex_color_set(ss, vd.vertex, orig_vert_data.col); | ||||
| } | } | ||||
| } | } | ||||
| BKE_pbvh_vertex_iter_end; | BKE_pbvh_vertex_iter_end; | ||||
| } | } | ||||
| static void paint_mesh_restore_co(Sculpt *sd, Object *ob) | static void paint_mesh_restore_co(Sculpt *sd, Object *ob) | ||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| ▲ Show 20 Lines • Show All 1,775 Lines • ▼ Show 20 Lines | static void do_brush_action_task_cb(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict UNUSED(tls)) | const TaskParallelTLS *__restrict UNUSED(tls)) | ||||
| { | { | ||||
| SculptThreadedTaskData *data = userdata; | SculptThreadedTaskData *data = userdata; | ||||
| SculptSession *ss = data->ob->sculpt; | SculptSession *ss = data->ob->sculpt; | ||||
| bool need_coords = ss->cache->supports_gravity; | bool need_coords = ss->cache->supports_gravity; | ||||
| /* Face Sets modifications do a single undo push */ | |||||
| if (data->brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) { | if (data->brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) { | ||||
| BKE_pbvh_node_mark_redraw(data->nodes[n]); | BKE_pbvh_node_mark_update_face_sets(data->nodes[n]); | ||||
| /* Draw face sets in smooth mode moves the vertices. */ | /* Draw face sets in smooth mode moves the vertices. */ | ||||
| if (ss->cache->alt_smooth) { | if (ss->cache->alt_smooth) { | ||||
| need_coords = true; | need_coords = true; | ||||
| } | } | ||||
| else { | |||||
| SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_FACE_SETS); | |||||
| } | |||||
| } | } | ||||
| else if (data->brush->sculpt_tool == SCULPT_TOOL_MASK) { | else if (data->brush->sculpt_tool == SCULPT_TOOL_MASK) { | ||||
| SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_MASK); | SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_MASK); | ||||
| BKE_pbvh_node_mark_update_mask(data->nodes[n]); | BKE_pbvh_node_mark_update_mask(data->nodes[n]); | ||||
| } | } | ||||
| else if (SCULPT_tool_is_paint(data->brush->sculpt_tool)) { | else if (SCULPT_tool_is_paint(data->brush->sculpt_tool)) { | ||||
| SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COLOR); | SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COLOR); | ||||
| BKE_pbvh_node_mark_update_color(data->nodes[n]); | BKE_pbvh_node_mark_update_color(data->nodes[n]); | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | static void do_brush_action(Sculpt *sd, | ||||
| } | } | ||||
| /* Draw Face Sets in draw mode makes a single undo push, in alt-smooth mode deforms the | /* Draw Face Sets in draw mode makes a single undo push, in alt-smooth mode deforms the | ||||
| * vertices and uses regular coords undo. */ | * vertices and uses regular coords undo. */ | ||||
| /* It also assigns the paint_face_set here as it needs to be done regardless of the stroke type | /* It also assigns the paint_face_set here as it needs to be done regardless of the stroke type | ||||
| * and the number of nodes under the brush influence. */ | * and the number of nodes under the brush influence. */ | ||||
| if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS && | if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS && | ||||
| SCULPT_stroke_is_first_brush_step(ss->cache) && !ss->cache->alt_smooth) { | SCULPT_stroke_is_first_brush_step(ss->cache) && !ss->cache->alt_smooth) { | ||||
| /* Dynamic-topology does not support Face Sets data, so it can't store/restore it from undo. */ | |||||
| /* TODO(pablodp606): This check should be done in the undo code and not here, but the rest of | |||||
| * the sculpt code is not checking for unsupported undo types that may return a null node. */ | |||||
| if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) { | |||||
| SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_FACE_SETS); | |||||
| } | |||||
| if (ss->cache->invert) { | if (ss->cache->invert) { | ||||
| /* When inverting the brush, pick the paint face mask ID from the mesh. */ | /* When inverting the brush, pick the paint face mask ID from the mesh. */ | ||||
| ss->cache->paint_face_set = SCULPT_active_face_set_get(ss); | ss->cache->paint_face_set = SCULPT_active_face_set_get(ss); | ||||
| } | } | ||||
| else { | else { | ||||
| /* By default create a new Face Sets. */ | /* By default create a new Face Sets. */ | ||||
| ss->cache->paint_face_set = SCULPT_face_set_next_available_get(ss); | ss->cache->paint_face_set = SCULPT_face_set_next_available_get(ss); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,813 Lines • ▼ Show 20 Lines | static void sculpt_restore_mesh(Sculpt *sd, Object *ob) | ||||
| } | } | ||||
| /* Restore the mesh before continuing with anchored stroke. */ | /* Restore the mesh before continuing with anchored stroke. */ | ||||
| if ((brush->flag & BRUSH_ANCHORED) || | if ((brush->flag & BRUSH_ANCHORED) || | ||||
| (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ELASTIC_DEFORM) && | (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ELASTIC_DEFORM) && | ||||
| BKE_brush_use_size_pressure(brush)) || | BKE_brush_use_size_pressure(brush)) || | ||||
| (brush->flag & BRUSH_DRAG_DOT)) { | (brush->flag & BRUSH_DRAG_DOT)) { | ||||
| SculptUndoNode *unode = SCULPT_undo_get_first_node(); | |||||
| if (unode && unode->type == SCULPT_UNDO_FACE_SETS) { | |||||
| for (int i = 0; i < ss->totfaces; i++) { | |||||
| ss->face_sets[i] = unode->face_sets[i]; | |||||
| } | |||||
| } | |||||
| paint_mesh_restore_co(sd, ob); | paint_mesh_restore_co(sd, ob); | ||||
| if (ss->cache) { | if (ss->cache) { | ||||
| MEM_SAFE_FREE(ss->cache->layer_displacement_factor); | MEM_SAFE_FREE(ss->cache->layer_displacement_factor); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 955 Lines • ▼ Show 20 Lines | ss->attrs.automasking_stroke_id = BKE_sculpt_attribute_ensure( | ||||
| ob, | ob, | ||||
| ATTR_DOMAIN_POINT, | ATTR_DOMAIN_POINT, | ||||
| CD_PROP_INT8, | CD_PROP_INT8, | ||||
| SCULPT_ATTRIBUTE_NAME(automasking_stroke_id), | SCULPT_ATTRIBUTE_NAME(automasking_stroke_id), | ||||
| ¶ms); | ¶ms); | ||||
| } | } | ||||
| } | } | ||||
| int SCULPT_face_set_get(const SculptSession *ss, PBVHFaceRef face) | |||||
| { | |||||
| switch (BKE_pbvh_type(ss->pbvh)) { | |||||
| case PBVH_BMESH: | |||||
| return 0; | |||||
| case PBVH_FACES: | |||||
| case PBVH_GRIDS: | |||||
| return ss->face_sets[face.i]; | |||||
| } | |||||
| BLI_assert_unreachable(); | |||||
| return 0; | |||||
| } | |||||
| void SCULPT_face_set_set(SculptSession *ss, PBVHFaceRef face, int fset) | |||||
| { | |||||
| switch (BKE_pbvh_type(ss->pbvh)) { | |||||
| case PBVH_BMESH: | |||||
| break; | |||||
| case PBVH_FACES: | |||||
| case PBVH_GRIDS: | |||||
| ss->face_sets[face.i] = fset; | |||||
| } | |||||
| } | |||||
| /** \} */ | /** \} */ | ||||