static int mask_flood_fill_exec(bContext *C, wmOperator *op) { ARegion *ar = CTX_wm_region(C); struct Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); PaintMaskFloodMode mode; float value; PBVH *pbvh; PBVHNode **nodes; int totnode, i; bool multires; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; mode = RNA_enum_get(op->ptr, "mode"); value = RNA_float_get(op->ptr, "value"); BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true); pbvh = ob->sculpt->pbvh; multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS); BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); sculpt_undo_push_begin("Mask flood fill"); #pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT) for (i = 0; i < totnode; i++) { PBVHVertexIter vi; sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK); BKE_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) { mask_flood_fill_set_elem(vi.mask, mode, value); } BKE_pbvh_vertex_iter_end; BKE_pbvh_node_mark_redraw(nodes[i]); if (multires) BKE_pbvh_node_mark_normals_update(nodes[i]); }
static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNode *unode) { Scene *scene = CTX_data_scene(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; MVert *mvert; int *index; if (unode->maxvert) { /* regular mesh restore */ if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) { /* shape key has been changed before calling undo operator */ Key *key = BKE_key_from_object(ob); KeyBlock *kb = key ? BKE_keyblock_find_name(key, unode->shapeName) : NULL; if (kb) { ob->shapenr = BLI_findindex(&key->block, kb) + 1; BKE_sculpt_update_mesh_elements(scene, sd, ob, false, false); WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); } else { /* key has been removed -- skip this undo node */ return 0; } } /* no need for float comparison here (memory is exactly equal or not) */ index = unode->index; mvert = ss->mvert; if (ss->kb) { float (*vertCos)[3]; vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->kb); if (unode->orig_co) { if (ss->modifiers_active) { for (int i = 0; i < unode->totvert; i++) { sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]); } } else { for (int i = 0; i < unode->totvert; i++) { swap_v3_v3(vertCos[index[i]], unode->orig_co[i]); } } } else { for (int i = 0; i < unode->totvert; i++) { swap_v3_v3(vertCos[index[i]], unode->co[i]); } } /* propagate new coords to keyblock */ sculpt_vertcos_to_key(ob, ss->kb, vertCos); /* pbvh uses it's own mvert array, so coords should be */ /* propagated to pbvh here */ BKE_pbvh_apply_vertCos(ss->pbvh, vertCos); MEM_freeN(vertCos); } else { if (unode->orig_co) { if (ss->modifiers_active) { for (int i = 0; i < unode->totvert; i++) { if (sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co)) { mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; } } } else { for (int i = 0; i < unode->totvert; i++) { if (test_swap_v3_v3(mvert[index[i]].co, unode->orig_co[i])) { mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; } } } } else { for (int i = 0; i < unode->totvert; i++) { if (test_swap_v3_v3(mvert[index[i]].co, unode->co[i])) { mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; } } } } } else if (unode->maxgrid && dm->getGridData) { /* multires restore */ CCGElem **grids, *grid; CCGKey key; float (*co)[3]; int gridsize; grids = dm->getGridData(dm); gridsize = dm->getGridSize(dm); dm->getGridKey(dm, &key); co = unode->co; for (int j = 0; j < unode->totgrid; j++) { grid = grids[unode->grids[j]]; for (int i = 0; i < gridsize * gridsize; i++, co++) { swap_v3_v3(CCG_elem_offset_co(&key, grid, i), co[0]); } } } return 1; }